Tomato 1.25
[tomato.git] / release / src / router / rc / interface.c
blobcd539be9be32e4e43866ed2ddf0a78b3659e1f1a
1 /*
2 * Linux network interface code
4 * Copyright 2005, Broadcom Corporation
5 * All Rights Reserved.
6 *
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 $
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <ctype.h>
18 #include <errno.h>
19 #include <error.h>
20 #include <string.h>
21 #include <unistd.h>
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>
31 #include <shutils.h>
32 #include <bcmnvram.h>
33 #include <bcmutils.h>
34 #include <bcmparams.h>
35 #include <bcmdevs.h>
36 #include <shared.h>
38 #include "rc.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)
46 int s;
47 struct ifreq ifr;
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)
61 goto ERROR;
63 /* Set IP address */
64 if (addr) {
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)
69 goto ERROR;
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)
78 goto ERROR;
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)
84 goto ERROR;
87 close(s);
88 return 0;
90 ERROR:
91 close(s);
92 perror(name);
93 return errno;
96 static int route_manip(int cmd, char *name, int metric, char *dst, char *gateway, char *genmask)
98 int s;
99 struct rtentry rt;
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));
109 if (dst)
110 inet_aton(dst, &sin_addr(&rt.rt_dst));
111 if (gateway)
112 inet_aton(gateway, &sin_addr(&rt.rt_gateway));
113 if (genmask)
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;
121 rt.rt_dev = name;
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) {
129 perror(name);
130 close(s);
131 return errno;
134 close(s);
135 return 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 */
160 int start_vlan(void)
162 int s;
163 struct ifreq ifr;
164 int i, j;
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)
174 return errno;
176 for (i = 0; i <= VLAN_MAXVID; i ++) {
177 char nvvar_name[16];
178 char vlan_id[16];
179 char *hwname, *hwaddr;
180 char prio[8];
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)))
184 continue;
185 snprintf(nvvar_name, sizeof(nvvar_name), "%smacaddr", hwname);
186 if (!(hwaddr = nvram_get(nvvar_name)))
187 continue;
188 ether_atoe(hwaddr, ea);
189 /* find the interface name to which the address is assigned */
190 for (j = 1; j <= DEV_NUMIFS; j ++) {
191 ifr.ifr_ifindex = j;
192 if (ioctl(s, SIOCGIFNAME, &ifr))
193 continue;
194 if (ioctl(s, SIOCGIFHWADDR, &ifr))
195 continue;
196 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
197 continue;
198 if (!bcmp(ifr.ifr_hwaddr.sa_data, ea, ETHER_ADDR_LEN))
199 break;
201 if (j > DEV_NUMIFS)
202 continue;
203 if (ioctl(s, SIOCGIFFLAGS, &ifr))
204 continue;
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);
218 close(s);
220 return 0;
223 /* stop/rem vlan interface(s) based on nvram settings */
224 int stop_vlan(void)
226 int i;
227 char nvvar_name[16];
228 char vlan_id[16];
229 char *hwname;
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)))
237 continue;
239 /* remove the VLAN interface */
240 snprintf(vlan_id, sizeof(vlan_id), "vlan%d", i);
241 eval("vconfig", "rem", vlan_id);
244 return 0;