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>
41 #define IFUP (IFF_UP | IFF_RUNNING | IFF_BROADCAST | IFF_MULTICAST)
42 #define sin_addr(s) (((struct sockaddr_in *)(s))->sin_addr)
44 int ifconfig(const char *name
, int flags
, const char *addr
, const char *netmask
)
48 struct in_addr in_addr
, in_netmask
, in_broadaddr
;
50 _dprintf("%s: name=%s flags=%s addr=%s netmask=%s\n", __FUNCTION__
, name
, flags
== IFUP
? "IFUP" : "0", addr
, netmask
);
52 /* Open a raw socket to the kernel */
53 if ((s
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0) return errno
;
55 /* Set interface name */
56 strlcpy(ifr
.ifr_name
, name
, IFNAMSIZ
);
58 /* Set interface flags */
59 ifr
.ifr_flags
= flags
;
60 if (ioctl(s
, SIOCSIFFLAGS
, &ifr
) < 0)
65 inet_aton(addr
, &in_addr
);
66 sin_addr(&ifr
.ifr_addr
).s_addr
= in_addr
.s_addr
;
67 ifr
.ifr_addr
.sa_family
= AF_INET
;
68 if (ioctl(s
, SIOCSIFADDR
, &ifr
) < 0)
72 /* Set IP netmask and broadcast */
73 if (addr
&& netmask
) {
74 inet_aton(netmask
, &in_netmask
);
75 sin_addr(&ifr
.ifr_netmask
).s_addr
= in_netmask
.s_addr
;
76 ifr
.ifr_netmask
.sa_family
= AF_INET
;
77 if (ioctl(s
, SIOCSIFNETMASK
, &ifr
) < 0)
80 in_broadaddr
.s_addr
= (in_addr
.s_addr
& in_netmask
.s_addr
) | ~in_netmask
.s_addr
;
81 sin_addr(&ifr
.ifr_broadaddr
).s_addr
= in_broadaddr
.s_addr
;
82 ifr
.ifr_broadaddr
.sa_family
= AF_INET
;
83 if (ioctl(s
, SIOCSIFBRDADDR
, &ifr
) < 0)
96 static int route_manip(int cmd
, char *name
, int metric
, char *dst
, char *gateway
, char *genmask
)
101 _dprintf("%s: cmd=%s name=%s addr=%s netmask=%s gateway=%s metric=%d\n",
102 __FUNCTION__
, cmd
== SIOCADDRT
? "ADD" : "DEL", name
, dst
, genmask
, gateway
, metric
);
104 /* Open a raw socket to the kernel */
105 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) return errno
;
107 /* Fill in rtentry */
108 memset(&rt
, 0, sizeof(rt
));
110 inet_aton(dst
, &sin_addr(&rt
.rt_dst
));
112 inet_aton(gateway
, &sin_addr(&rt
.rt_gateway
));
114 inet_aton(genmask
, &sin_addr(&rt
.rt_genmask
));
115 rt
.rt_metric
= metric
;
116 rt
.rt_flags
= RTF_UP
;
117 if (sin_addr(&rt
.rt_gateway
).s_addr
)
118 rt
.rt_flags
|= RTF_GATEWAY
;
119 if (sin_addr(&rt
.rt_genmask
).s_addr
== INADDR_BROADCAST
)
120 rt
.rt_flags
|= RTF_HOST
;
123 /* Force address family to AF_INET */
124 rt
.rt_dst
.sa_family
= AF_INET
;
125 rt
.rt_gateway
.sa_family
= AF_INET
;
126 rt
.rt_genmask
.sa_family
= AF_INET
;
128 if (ioctl(s
, cmd
, &rt
) < 0) {
139 int route_add(char *name
, int metric
, char *dst
, char *gateway
, char *genmask
)
141 return route_manip(SIOCADDRT
, name
, metric
, dst
, gateway
, genmask
);
144 int route_del(char *name
, int metric
, char *dst
, char *gateway
, char *genmask
)
146 return route_manip(SIOCDELRT
, name
, metric
, dst
, gateway
, genmask
);
149 /* configure loopback interface */
150 void config_loopback(void)
152 /* Bring up loopback interface */
153 ifconfig("lo", IFUP
, "127.0.0.1", "255.0.0.0");
155 /* Add to routing table */
156 route_add("lo", 0, "127.0.0.0", "0.0.0.0", "255.0.0.0");
159 /* configure/start vlan interface(s) based on nvram settings */
165 char ea
[ETHER_ADDR_LEN
];
167 if ((strtoul(nvram_safe_get("boardflags"), NULL
, 0) & BFL_ENETVLAN
) == 0) return 0;
169 /* set vlan i/f name to style "vlan<ID>" */
170 eval("vconfig", "set_name_type", "VLAN_PLUS_VID_NO_PAD");
172 /* create vlan interfaces */
173 if ((s
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0)
176 for (i
= 0; i
<= VLAN_MAXVID
; i
++) {
179 char *hwname
, *hwaddr
;
181 /* get the address of the EMAC on which the VLAN sits */
182 snprintf(nvvar_name
, sizeof(nvvar_name
), "vlan%dhwname", i
);
183 if (!(hwname
= nvram_get(nvvar_name
)))
185 snprintf(nvvar_name
, sizeof(nvvar_name
), "%smacaddr", hwname
);
186 if (!(hwaddr
= nvram_get(nvvar_name
)))
188 ether_atoe(hwaddr
, ea
);
189 /* find the interface name to which the address is assigned */
190 for (j
= 1; j
<= DEV_NUMIFS
; j
++) {
192 if (ioctl(s
, SIOCGIFNAME
, &ifr
))
194 if (ioctl(s
, SIOCGIFHWADDR
, &ifr
))
196 if (ifr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
)
198 if (!bcmp(ifr
.ifr_hwaddr
.sa_data
, ea
, ETHER_ADDR_LEN
))
203 if (ioctl(s
, SIOCGIFFLAGS
, &ifr
))
205 if (!(ifr
.ifr_flags
& IFF_UP
))
206 ifconfig(ifr
.ifr_name
, IFUP
, 0, 0);
207 /* create the VLAN interface */
208 snprintf(vlan_id
, sizeof(vlan_id
), "%d", i
);
209 eval("vconfig", "add", ifr
.ifr_name
, vlan_id
);
210 /* setup ingress map (vlan->priority => skb->priority) */
211 snprintf(vlan_id
, sizeof(vlan_id
), "vlan%d", i
);
212 for (j
= 0; j
< VLAN_NUMPRIS
; j
++) {
213 snprintf(prio
, sizeof(prio
), "%d", j
);
214 eval("vconfig", "set_ingress_map", vlan_id
, prio
, prio
);
223 /* stop/rem vlan interface(s) based on nvram settings */
231 if ((strtoul(nvram_safe_get("boardflags"), NULL
, 0) & BFL_ENETVLAN
) == 0) return 0;
233 for (i
= 0; i
<= VLAN_MAXVID
; i
++) {
234 /* get the address of the EMAC on which the VLAN sits */
235 snprintf(nvvar_name
, sizeof(nvvar_name
), "vlan%dhwname", i
);
236 if (!(hwname
= nvram_get(nvvar_name
)))
239 /* remove the VLAN interface */
240 snprintf(vlan_id
, sizeof(vlan_id
), "vlan%d", i
);
241 eval("vconfig", "rem", vlan_id
);