1/* 2 * Linux network interface code 3 * 4 * Copyright 2004, 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. 11 * 12 * $Id: interface.c,v 1.1.1.1 2008/10/15 03:28:48 james26_jang Exp $ 13 */ 14 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/if.h> 26#include <net/route.h> 27#include <netinet/in.h> 28#include <arpa/inet.h> 29#include <net/if_arp.h> 30#include <proto/ethernet.h> 31#include <shutils.h> 32#include <bcmnvram.h> 33#include <bcmutils.h> 34#include <bcmparams.h> 35#include <rc.h> 36 37in_addr_t 38inet_addr_(const char *cp) 39{ 40 struct in_addr a; 41 42 if (!inet_aton(cp, &a)) 43 return INADDR_ANY; 44 else 45 return a.s_addr; 46} 47 48 49int 50ifconfig(char *name, int flags, char *addr, char *netmask) 51{ 52 int s; 53 struct ifreq ifr; 54 struct in_addr in_addr, in_netmask, in_broadaddr; 55 56 /* Open a raw socket to the kernel */ 57 if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) 58 goto err; 59 60 /* Set interface name */ 61 strncpy(ifr.ifr_name, name, IFNAMSIZ); 62 63 /* Set interface flags */ 64 ifr.ifr_flags = flags; 65 if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) 66 goto err; 67 68 /* Set IP address */ 69 if (addr) { 70 inet_aton(addr, &in_addr); 71 sin_addr(&ifr.ifr_addr).s_addr = in_addr.s_addr; 72 ifr.ifr_addr.sa_family = AF_INET; 73 if (ioctl(s, SIOCSIFADDR, &ifr) < 0) 74 goto err; 75 } 76 77 /* Set IP netmask and broadcast */ 78 if (addr && netmask) { 79 inet_aton(netmask, &in_netmask); 80 sin_addr(&ifr.ifr_netmask).s_addr = in_netmask.s_addr; 81 ifr.ifr_netmask.sa_family = AF_INET; 82 if (ioctl(s, SIOCSIFNETMASK, &ifr) < 0) 83 goto err; 84 85 in_broadaddr.s_addr = (in_addr.s_addr & in_netmask.s_addr) | ~in_netmask.s_addr; 86 sin_addr(&ifr.ifr_broadaddr).s_addr = in_broadaddr.s_addr; 87 ifr.ifr_broadaddr.sa_family = AF_INET; 88 if (ioctl(s, SIOCSIFBRDADDR, &ifr) < 0) 89 goto err; 90 } 91 92 close(s); 93 94 return 0; 95 96 err: 97 close(s); 98 perror(name); 99 return errno; 100} 101 102static int 103route_manip(int cmd, char *name, int metric, char *dst, char *gateway, char *genmask) 104{ 105 int s; 106 struct rtentry rt; 107 108 /* Open a raw socket to the kernel */ 109 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 110 goto err; 111 112 /* Fill in rtentry */ 113 memset(&rt, 0, sizeof(rt)); 114 if (dst) 115 inet_aton(dst, &sin_addr(&rt.rt_dst)); 116 if (gateway) 117 inet_aton(gateway, &sin_addr(&rt.rt_gateway)); 118 if (genmask) 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; 126 rt.rt_dev = name; 127 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; 132 133 if (ioctl(s, cmd, &rt) < 0) 134 goto err; 135 136 close(s); 137 return 0; 138 139 err: 140 close(s); 141 perror(name); 142 return errno; 143} 144 145int 146route_add(char *name, int metric, char *dst, char *gateway, char *genmask) 147{ 148 return route_manip(SIOCADDRT, name, metric, dst, gateway, genmask); 149} 150 151int 152route_del(char *name, int metric, char *dst, char *gateway, char *genmask) 153{ 154 return route_manip(SIOCDELRT, name, metric, dst, gateway, genmask); 155} 156 157/* configure loopback interface */ 158void 159config_loopback(void) 160{ 161 /* Bring up loopback interface */ 162 ifconfig("lo", IFUP, "127.0.0.1", "255.0.0.0"); 163 164 /* Add to routing table */ 165 route_add("lo", 0, "127.0.0.0", "0.0.0.0", "255.0.0.0"); 166} 167 168#ifndef CONFIG_SENTRY5 169/* configure/start vlan interface(s) based on nvram settings */ 170int 171start_vlan(void) 172{ 173 int s; 174 struct ifreq ifr; 175 int i, j; 176 char ea[ETHER_ADDR_LEN]; 177 178 /* set vlan i/f name to style "vlan<ID>" */ 179 //printf("vconfig setname_type VLAN_PLUS_VID_NO_PAD\n"); 180 eval("vconfig", "set_name_type", "VLAN_PLUS_VID_NO_PAD"); 181 182 /* create vlan interfaces */ 183 if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) 184 return errno; 185 186 for (i = 0; i <= VLAN_MAXVID; i ++) { 187 char nvvar_name[16]; 188 char vlan_id[16]; 189 char *hwname, *hwaddr; 190 char prio[8]; 191 /* get the address of the EMAC on which the VLAN sits */ 192 snprintf(nvvar_name, sizeof(nvvar_name), "vlan%dhwname", i); 193 if (!(hwname = nvram_get(nvvar_name))) 194 continue; 195 snprintf(nvvar_name, sizeof(nvvar_name), "%smacaddr", hwname); 196 if (!(hwaddr = nvram_get(nvvar_name))) 197 continue; 198 ether_atoe(hwaddr, ea); 199 /* find the interface name to which the address is assigned */ 200 for (j = 1; j <= DEV_NUMIFS; j ++) { 201 ifr.ifr_ifindex = j; 202 if (ioctl(s, SIOCGIFNAME, &ifr)) 203 continue; 204 if (ioctl(s, SIOCGIFHWADDR, &ifr)) 205 continue; 206 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) 207 continue; 208 if (!bcmp(ifr.ifr_hwaddr.sa_data, ea, ETHER_ADDR_LEN)) 209 break; 210 } 211 if (j > DEV_NUMIFS) 212 continue; 213 if (ioctl(s, SIOCGIFFLAGS, &ifr)) 214 continue; 215 if (!(ifr.ifr_flags & IFF_UP)) 216 ifconfig(ifr.ifr_name, IFUP, 0, 0); 217 /* create the VLAN interface */ 218 snprintf(vlan_id, sizeof(vlan_id), "%d", i); 219 //printf("vconfig add %s %s\n", ifr.ifr_name, vlan_id); 220 eval("vconfig", "add", ifr.ifr_name, vlan_id); 221 /* setup ingress map (vlan->priority => skb->priority) */ 222 snprintf(vlan_id, sizeof(vlan_id), "vlan%d", i); 223 for (j = 0; j < VLAN_NUMPRIS; j ++) { 224 snprintf(prio, sizeof(prio), "%d", j); 225 //printf("vconfig set_ingress_map %s %s %s\n", vlan_id, prio, prio); 226 eval("vconfig", "set_ingress_map", vlan_id, prio, prio); 227 } 228 } 229 230 close(s); 231 232 return 0; 233} 234 235/* stop/rem vlan interface(s) based on nvram settings */ 236int 237stop_vlan(void) 238{ 239 int i; 240 char nvvar_name[16]; 241 char vlan_id[16]; 242 char *hwname; 243 244 for (i = 0; i <= VLAN_MAXVID; i ++) { 245 /* get the address of the EMAC on which the VLAN sits */ 246 snprintf(nvvar_name, sizeof(nvvar_name), "vlan%dhwname", i); 247 if (!(hwname = nvram_get(nvvar_name))) 248 continue; 249 250 /* remove the VLAN interface */ 251 snprintf(vlan_id, sizeof(vlan_id), "vlan%d", i); 252 //printf("vconfig rem %s\n", vlan_id); 253 eval("vconfig", "rem", vlan_id); 254 } 255 256 return 0; 257} 258#endif 259