2 * Linux network interface code
4 * Copyright 2005, Broadcom Corporation
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
12 * $Id: interface.c,v 1.13 2005/03/07 08:35:32 kanki Exp $
22 #include <sys/ioctl.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <net/route.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28 #include <net/if_arp.h>
29 #include <proto/ethernet.h>
34 #include <bcmparams.h>
40 int _ifconfig(const char *name
, int flags
, const char *addr
, const char *netmask
, const char *dstaddr
)
44 struct in_addr in_addr
, in_netmask
, in_broadaddr
;
46 _dprintf("%s: name=%s flags=%s addr=%s netmask=%s\n", __FUNCTION__
, name
, flags
== IFUP
? "IFUP" : "0", addr
, netmask
);
48 /* Open a raw socket to the kernel */
49 if ((s
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0) return errno
;
51 /* Set interface name */
52 strlcpy(ifr
.ifr_name
, name
, IFNAMSIZ
);
54 /* Set interface flags */
55 ifr
.ifr_flags
= flags
;
56 if (ioctl(s
, SIOCSIFFLAGS
, &ifr
) < 0)
61 inet_aton(addr
, &in_addr
);
62 sin_addr(&ifr
.ifr_addr
).s_addr
= in_addr
.s_addr
;
63 ifr
.ifr_addr
.sa_family
= AF_INET
;
64 if (ioctl(s
, SIOCSIFADDR
, &ifr
) < 0)
68 /* Set IP netmask and broadcast */
69 if (addr
&& netmask
) {
70 inet_aton(netmask
, &in_netmask
);
71 sin_addr(&ifr
.ifr_netmask
).s_addr
= in_netmask
.s_addr
;
72 ifr
.ifr_netmask
.sa_family
= AF_INET
;
73 if (ioctl(s
, SIOCSIFNETMASK
, &ifr
) < 0)
76 in_broadaddr
.s_addr
= (in_addr
.s_addr
& in_netmask
.s_addr
) | ~in_netmask
.s_addr
;
77 sin_addr(&ifr
.ifr_broadaddr
).s_addr
= in_broadaddr
.s_addr
;
78 ifr
.ifr_broadaddr
.sa_family
= AF_INET
;
79 if (ioctl(s
, SIOCSIFBRDADDR
, &ifr
) < 0)
83 /* Set dst or P-t-P IP address */
85 inet_aton(dstaddr
, &in_addr
);
86 sin_addr(&ifr
.ifr_dstaddr
).s_addr
= in_addr
.s_addr
;
87 ifr
.ifr_dstaddr
.sa_family
= AF_INET
;
88 if (ioctl(s
, SIOCSIFDSTADDR
, &ifr
) < 0)
101 static int route_manip(int cmd
, char *name
, int metric
, char *dst
, char *gateway
, char *genmask
)
106 _dprintf("%s: cmd=%s name=%s addr=%s netmask=%s gateway=%s metric=%d\n",
107 __FUNCTION__
, cmd
== SIOCADDRT
? "ADD" : "DEL", name
, dst
, genmask
, gateway
, metric
);
109 /* Open a raw socket to the kernel */
110 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) return errno
;
112 /* Fill in rtentry */
113 memset(&rt
, 0, sizeof(rt
));
115 inet_aton(dst
, &sin_addr(&rt
.rt_dst
));
117 inet_aton(gateway
, &sin_addr(&rt
.rt_gateway
));
119 inet_aton(genmask
, &sin_addr(&rt
.rt_genmask
));
120 rt
.rt_metric
= metric
;
121 rt
.rt_flags
= RTF_UP
;
122 if (sin_addr(&rt
.rt_gateway
).s_addr
)
123 rt
.rt_flags
|= RTF_GATEWAY
;
124 if (sin_addr(&rt
.rt_genmask
).s_addr
== INADDR_BROADCAST
)
125 rt
.rt_flags
|= RTF_HOST
;
128 /* Force address family to AF_INET */
129 rt
.rt_dst
.sa_family
= AF_INET
;
130 rt
.rt_gateway
.sa_family
= AF_INET
;
131 rt
.rt_genmask
.sa_family
= AF_INET
;
133 if (ioctl(s
, cmd
, &rt
) < 0) {
144 int route_add(char *name
, int metric
, char *dst
, char *gateway
, char *genmask
)
146 return route_manip(SIOCADDRT
, name
, metric
+ 1, dst
, gateway
, genmask
);
149 void route_del(char *name
, int metric
, char *dst
, char *gateway
, char *genmask
)
151 while (route_manip(SIOCDELRT
, name
, metric
+ 1, dst
, gateway
, genmask
) == 0) {
156 /* configure loopback interface */
157 void config_loopback(void)
159 /* Bring up loopback interface */
160 ifconfig("lo", IFUP
, "127.0.0.1", "255.0.0.0");
162 /* Add to routing table */
163 route_add("lo", 0, "127.0.0.0", "0.0.0.0", "255.0.0.0");
166 /* configure/start vlan interface(s) based on nvram settings */
172 char ea
[ETHER_ADDR_LEN
];
174 if ((strtoul(nvram_safe_get("boardflags"), NULL
, 0) & BFL_ENETVLAN
) == 0) return 0;
176 /* set vlan i/f name to style "vlan<ID>" */
177 eval("vconfig", "set_name_type", "VLAN_PLUS_VID_NO_PAD");
179 /* create vlan interfaces */
180 if ((s
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0)
183 vlan0tag
= nvram_get_int("vlan0tag");
185 for (i
= 0; i
<= VLAN_MAXVID
; i
++) {
188 char *hwname
, *hwaddr
;
190 /* get the address of the EMAC on which the VLAN sits */
191 snprintf(nvvar_name
, sizeof(nvvar_name
), "vlan%dhwname", i
);
192 if (!(hwname
= nvram_get(nvvar_name
)))
194 snprintf(nvvar_name
, sizeof(nvvar_name
), "%smacaddr", hwname
);
195 if (!(hwaddr
= nvram_get(nvvar_name
)))
197 ether_atoe(hwaddr
, ea
);
198 /* find the interface name to which the address is assigned */
199 for (j
= 1; j
<= DEV_NUMIFS
; j
++) {
201 if (ioctl(s
, SIOCGIFNAME
, &ifr
))
203 if (ioctl(s
, SIOCGIFHWADDR
, &ifr
))
205 if (ifr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
)
207 if (!bcmp(ifr
.ifr_hwaddr
.sa_data
, ea
, ETHER_ADDR_LEN
))
212 if (ioctl(s
, SIOCGIFFLAGS
, &ifr
))
214 if (!(ifr
.ifr_flags
& IFF_UP
))
215 ifconfig(ifr
.ifr_name
, IFUP
, 0, 0);
216 /* create the VLAN interface */
217 snprintf(vlan_id
, sizeof(vlan_id
), "%d", i
| vlan0tag
);
218 eval("vconfig", "add", ifr
.ifr_name
, vlan_id
);
219 /* setup ingress map (vlan->priority => skb->priority) */
220 snprintf(vlan_id
, sizeof(vlan_id
), "vlan%d", i
| vlan0tag
);
221 for (j
= 0; j
< VLAN_NUMPRIS
; j
++) {
222 snprintf(prio
, sizeof(prio
), "%d", j
);
223 eval("vconfig", "set_ingress_map", vlan_id
, prio
, prio
);
232 /* stop/rem vlan interface(s) based on nvram settings */
240 if ((strtoul(nvram_safe_get("boardflags"), NULL
, 0) & BFL_ENETVLAN
) == 0) return 0;
242 for (i
= 0; i
<= VLAN_MAXVID
; i
++) {
243 /* get the address of the EMAC on which the VLAN sits */
244 snprintf(nvvar_name
, sizeof(nvvar_name
), "vlan%dhwname", i
);
245 if (!(hwname
= nvram_get(nvvar_name
)))
248 /* remove the VLAN interface */
249 snprintf(vlan_id
, sizeof(vlan_id
), "vlan%d", i
| nvram_get_int("vlan0tag"));
250 eval("vconfig", "rem", vlan_id
);