1/* 2 * Linux network interface code 3 * 4 * Copyright (C) 2014, Broadcom Corporation. All Rights Reserved. 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * $Id: interface.c 291523 2011-10-24 06:12:27Z $ 19 */ 20 21#include <stdio.h> 22#include <stdlib.h> 23#include <ctype.h> 24#include <errno.h> 25#include <error.h> 26#include <string.h> 27#include <unistd.h> 28#include <sys/ioctl.h> 29#include <sys/types.h> 30#include <sys/socket.h> 31#include <linux/route.h> 32#include <linux/if.h> 33#include <linux/sockios.h> 34#include <linux/ethtool.h> 35#include <netinet/in.h> 36#include <arpa/inet.h> 37#include <net/if_arp.h> 38#include <proto/ethernet.h> 39#include <shutils.h> 40#include <bcmnvram.h> 41#include <bcmutils.h> 42#include <bcmparams.h> 43#include <rc.h> 44 45int 46ifconfig(char *name, int flags, char *addr, char *netmask) 47{ 48 int s; 49 struct ifreq ifr; 50 struct in_addr in_addr, in_netmask, in_broadaddr; 51 52 /* Open a raw socket to the kernel */ 53 if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) 54 goto err; 55 56 /* Set interface name */ 57 strncpy(ifr.ifr_name, name, IFNAMSIZ); 58 59 /* Set interface flags */ 60 ifr.ifr_flags = flags; 61 if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) 62 goto err; 63 64 /* Set IP address */ 65 if (addr) { 66 inet_aton(addr, &in_addr); 67 sin_addr(&ifr.ifr_addr).s_addr = in_addr.s_addr; 68 ifr.ifr_addr.sa_family = AF_INET; 69 if (ioctl(s, SIOCSIFADDR, &ifr) < 0) 70 goto err; 71 } 72 73 /* Set IP netmask and broadcast */ 74 if (addr && netmask) { 75 inet_aton(netmask, &in_netmask); 76 sin_addr(&ifr.ifr_netmask).s_addr = in_netmask.s_addr; 77 ifr.ifr_netmask.sa_family = AF_INET; 78 if (ioctl(s, SIOCSIFNETMASK, &ifr) < 0) 79 goto err; 80 81 in_broadaddr.s_addr = (in_addr.s_addr & in_netmask.s_addr) | ~in_netmask.s_addr; 82 sin_addr(&ifr.ifr_broadaddr).s_addr = in_broadaddr.s_addr; 83 ifr.ifr_broadaddr.sa_family = AF_INET; 84 if (ioctl(s, SIOCSIFBRDADDR, &ifr) < 0) 85 goto err; 86 } 87 88 close(s); 89 90 return 0; 91 92err: 93 close(s); 94 perror(name); 95 return errno; 96} 97 98int 99ifconfig_get(char *name, int *flags, unsigned long *addr, unsigned long *netmask) 100{ 101 int s; 102 struct ifreq ifr; 103 104 /* Open a raw socket to the kernel */ 105 if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) 106 goto err; 107 108 /* Set interface name */ 109 strncpy(ifr.ifr_name, name, IFNAMSIZ); 110 111 /* Check MAC first */ 112 if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) 113 goto err; 114 else if (memcmp(ifr.ifr_hwaddr.sa_data, "\0\0\0\0\0\0", 6) == 0) 115 goto err; 116 117 /* Get interface flags */ 118 if (flags) { 119 if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) 120 goto err; 121 else 122 memcpy(flags, &(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr), 123 sizeof(*flags)); 124 } 125 126 /* Get IP address */ 127 if (addr) { 128 if (ioctl(s, SIOCGIFADDR, &ifr) < 0) 129 goto err; 130 else 131 memcpy(addr, &(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr), 132 sizeof(*addr)); 133 } 134 135 /* Get Net mask */ 136 if (netmask) { 137 if (ioctl(s, SIOCGIFNETMASK, &ifr) < 0) 138 goto err; 139 else { 140 memcpy(netmask, &(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr), 141 sizeof(*netmask)); 142 } 143 } 144 145 close(s); 146 147 return 0; 148 149err: 150 close(s); 151 perror(name); 152 return errno; 153} 154 155static int 156route_manip(int cmd, char *name, int metric, char *dst, char *gateway, char *genmask) 157{ 158 int s; 159 struct rtentry rt; 160 161 /* Open a raw socket to the kernel */ 162 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 163 goto err; 164 165 /* Fill in rtentry */ 166 memset(&rt, 0, sizeof(rt)); 167 if (dst) 168 inet_aton(dst, &sin_addr(&rt.rt_dst)); 169 if (gateway) 170 inet_aton(gateway, &sin_addr(&rt.rt_gateway)); 171 if (genmask) 172 inet_aton(genmask, &sin_addr(&rt.rt_genmask)); 173 rt.rt_metric = metric; 174 rt.rt_flags = RTF_UP; 175 if (sin_addr(&rt.rt_gateway).s_addr) 176 rt.rt_flags |= RTF_GATEWAY; 177 if (sin_addr(&rt.rt_genmask).s_addr == INADDR_BROADCAST) 178 rt.rt_flags |= RTF_HOST; 179 rt.rt_dev = name; 180 181 /* Force address family to AF_INET */ 182 rt.rt_dst.sa_family = AF_INET; 183 rt.rt_gateway.sa_family = AF_INET; 184 rt.rt_genmask.sa_family = AF_INET; 185 186 if (ioctl(s, cmd, &rt) < 0) 187 goto err; 188 189 close(s); 190 return 0; 191 192err: 193 close(s); 194 perror(name); 195 return errno; 196} 197 198int 199route_add(char *name, int metric, char *dst, char *gateway, char *genmask) 200{ 201 return route_manip(SIOCADDRT, name, metric, dst, gateway, genmask); 202} 203 204int 205route_del(char *name, int metric, char *dst, char *gateway, char *genmask) 206{ 207 return route_manip(SIOCDELRT, name, metric, dst, gateway, genmask); 208} 209 210/* configure loopback interface */ 211void 212config_loopback(void) 213{ 214 /* Bring up loopback interface */ 215 ifconfig("lo", IFUP, "127.0.0.1", "255.0.0.0"); 216 217 /* Add to routing table */ 218 route_add("lo", 0, "127.0.0.0", "0.0.0.0", "255.0.0.0"); 219} 220 221void update_port_priority(int vlan_id,char *vlan_interface,int priority) 222{ 223 char *ports; 224 char vlanxxports[64]; 225 226 sprintf(vlanxxports,"vlan%dports",vlan_id); 227 228 ports=acosNvramConfig_get(vlanxxports); 229 230 if(strlen(ports)) 231 { 232 char port_str[32],*next; 233 int port; 234 char priority_command[64]; 235 foreach(port_str, ports, next) { 236 port=atoi(port_str); 237#if defined(R8000) 238 if(port==5 || port == 4) // WAN port or CPU port 239 break; 240#else 241 if(port==5 || port == 0) // WAN port or CPU port 242 break; 243#endif 244 sprintf(priority_command,"et robowr 0x34 %d %d",0x10+port*2,vlan_id+(priority << 13)); 245 system(priority_command); 246 } 247 } 248} 249 250/* configure/start vlan interface(s) based on nvram settings */ 251int 252start_vlan(void) 253{ 254 int s; 255 struct ifreq ifr; 256 int i, j; 257 unsigned char ea[ETHER_ADDR_LEN]; 258 char buf[256]; 259 260 261 262 /* Bob added start, 09/03/2009, to avoid sending router solicitation packets */ 263#ifdef INCLUDE_IPV6 264 system("echo 0 > /proc/sys/net/ipv6/conf/all/router_solicitations"); 265 system("echo 0 > /proc/sys/net/ipv6/conf/default/router_solicitations"); // pling added 08/16/2010 266#endif 267 /* Bob added end, 09/03/2009, to avoid sending router solicitation packets */ 268 269 /* set vlan i/f name to style "vlan<ID>" */ 270 eval("vconfig", "set_name_type", "VLAN_PLUS_VID_NO_PAD"); 271 272 /* create vlan interfaces */ 273 if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) 274 return errno; 275 276 for (i = 0; i <= VLAN_MAXVID; i ++) 277 { 278 char nvvar_name[16]; 279 char vlan_id[16]; 280 char *hwname, *hwaddr; 281 char prio[8]; 282 283 /* get the address of the EMAC on which the VLAN sits */ 284 snprintf(nvvar_name, sizeof(nvvar_name), "vlan%dhwname", i); 285 if (!(hwname = nvram_get(nvvar_name))) 286 continue; 287 snprintf(nvvar_name, sizeof(nvvar_name), "%smacaddr", hwname); 288 if (!(hwaddr = nvram_get(nvvar_name))) 289 continue; 290 ether_atoe(hwaddr, ea); 291 /* find the interface name to which the address is assigned */ 292 for (j = 1; j <= DEV_NUMIFS; j ++) { 293 ifr.ifr_ifindex = j; 294 if (ioctl(s, SIOCGIFNAME, &ifr)) 295 continue; 296 if (ioctl(s, SIOCGIFHWADDR, &ifr)) 297 continue; 298 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) 299 continue; 300 if (!bcmp(ifr.ifr_hwaddr.sa_data, ea, ETHER_ADDR_LEN)) 301 break; 302 } 303 if (j > DEV_NUMIFS) 304 continue; 305 if (ioctl(s, SIOCGIFFLAGS, &ifr)) 306 continue; 307 308 /* Bob added start, 09/03/2009, to avoid sending router solicitation packets */ 309#ifdef INCLUDE_IPV6 310 sprintf(buf, "echo 0 > /proc/sys/net/ipv6/conf/%s/router_solicitations", ifr.ifr_name); 311 system(buf); 312#endif 313 /* Bob added end, 09/03/2009, to avoid sending router solicitation packets */ 314 315 if (!(ifr.ifr_flags & IFF_UP)) 316 ifconfig(ifr.ifr_name, IFUP, 0, 0); 317 /* create the VLAN interface */ 318 sprintf(vlan_id,"%d", i); 319 eval("vconfig", "add", ifr.ifr_name, vlan_id); 320 /* setup ingress map (vlan->priority => skb->priority) */ 321 sprintf(vlan_id, "vlan%d", i); 322 /* Bob added start, 09/03/2009, to avoid sending router solicitation packets */ 323#ifdef INCLUDE_IPV6 324 sprintf(buf, "echo 0 > /proc/sys/net/ipv6/conf/%s/router_solicitations", vlan_id); 325 system(buf); 326#endif 327 /* Bob added end, 09/03/2009, to avoid sending router solicitation packets */ 328 for (j = 0; j < VLAN_NUMPRIS; j ++) { 329 sprintf(prio, "%d", j); 330 eval("vconfig", "set_ingress_map", vlan_id, prio, prio); 331 332/*Foxconn add start, edward zhang, 2013/07/03*/ 333#ifdef VLAN_SUPPORT 334 335 /*setup egress vlan priority*/ 336 if(nvram_match("enable_vlan","enable")) 337 { 338 char vlan_prio[16]; 339 sprintf(vlan_prio,"%s_prio",vlan_id); 340 if(nvram_get(vlan_prio)) 341 { 342 update_port_priority(i,vlan_id,atoi(nvram_get(vlan_prio))); 343 if(i==atoi(nvram_get("internet_vlan"))) 344 { 345 if(j==0) 346 { 347 eval("vconfig", "set_egress_map",vlan_id, "0", nvram_get("internet_prio")); 348 } 349 } 350 else 351 eval("vconfig", "set_egress_map",vlan_id, prio, nvram_get(vlan_prio)); 352 } 353 } 354#endif 355/*Foxconn add end, edward zhang, 2013/07/03*/ 356 } 357 } 358 359 /* Bob added start 09/03/2009 */ 360#ifdef INCLUDE_IPV6 361 if (nvram_match("ipv6ready", "1")) 362 { 363 char cmd[32]; 364 sprintf(cmd, "ifconfig %s hw ether %s",nvram_get("lan_interface"), nvram_get("lan_hwaddr")); 365 system(cmd); 366 } 367#endif 368 /* Bob added end 09/03/2009 */ 369 370 close(s); 371 372 return 0; 373} 374 375/* stop/rem vlan interface(s) based on nvram settings */ 376int 377stop_vlan(void) 378{ 379 int i; 380 char nvvar_name[16]; 381 char vlan_id[16]; 382 char *hwname; 383 384 for (i = 0; i <= VLAN_MAXVID; i ++) { 385 /* get the address of the EMAC on which the VLAN sits */ 386 snprintf(nvvar_name, sizeof(nvvar_name), "vlan%dhwname", i); 387 if (!(hwname = nvram_get(nvvar_name))) 388 continue; 389 390 /* remove the VLAN interface */ 391 snprintf(vlan_id, sizeof(vlan_id), "vlan%d", i); 392 eval("vconfig", "rem", vlan_id); 393 } 394 395 return 0; 396} 397