1/*
2 * Linux network interface code
3 *
4 * Copyright 2003, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
8 * the contents of this file may not be disclosed to third parties, copied
9 * or duplicated in any form, in whole or in part, without the prior
10 * written permission of Broadcom Corporation.
11 *
12 * $Id: interface.c,v 1.1.1.1 2008/07/21 09:17:45 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
31#define sin_addr(s) (((struct sockaddr_in *)(s))->sin_addr)
32
33int
34ifconfig(char *name, int flags, char *addr, char *netmask)
35{
36	int s;
37	struct ifreq ifr;
38	struct in_addr in_addr, in_netmask, in_broadaddr;
39
40	/* Open a raw socket to the kernel */
41	if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
42		goto err;
43
44	/* Set interface name */
45	strncpy(ifr.ifr_name, name, IFNAMSIZ);
46
47	/* Set interface flags */
48	ifr.ifr_flags = flags;
49	if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0)
50		goto err;
51
52	/* Set IP address */
53	if (addr) {
54		inet_aton(addr, &in_addr);
55		sin_addr(&ifr.ifr_addr).s_addr = in_addr.s_addr;
56		ifr.ifr_addr.sa_family = AF_INET;
57		if (ioctl(s, SIOCSIFADDR, &ifr) < 0)
58			goto err;
59	}
60
61	/* Set IP netmask and broadcast */
62	if (addr && netmask) {
63		inet_aton(netmask, &in_netmask);
64		sin_addr(&ifr.ifr_netmask).s_addr = in_netmask.s_addr;
65		ifr.ifr_netmask.sa_family = AF_INET;
66		if (ioctl(s, SIOCSIFNETMASK, &ifr) < 0)
67			goto err;
68
69		in_broadaddr.s_addr = (in_addr.s_addr & in_netmask.s_addr) | ~in_netmask.s_addr;
70		sin_addr(&ifr.ifr_broadaddr).s_addr = in_broadaddr.s_addr;
71		ifr.ifr_broadaddr.sa_family = AF_INET;
72		if (ioctl(s, SIOCSIFBRDADDR, &ifr) < 0)
73			goto err;
74	}
75
76	close(s);
77	return 0;
78
79 err:
80	close(s);
81	perror(name);
82	return errno;
83}
84
85static int
86route_manip(int cmd, char *name, int metric, char *dst, char *gateway, char *genmask)
87{
88	int s;
89	struct rtentry rt;
90
91	/* Open a raw socket to the kernel */
92	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
93		goto err;
94
95	/* Fill in rtentry */
96	memset(&rt, 0, sizeof(rt));
97	if (dst)
98		inet_aton(dst, &sin_addr(&rt.rt_dst));
99	if (gateway)
100		inet_aton(gateway, &sin_addr(&rt.rt_gateway));
101	if (genmask)
102		inet_aton(genmask, &sin_addr(&rt.rt_genmask));
103	rt.rt_metric = metric;
104	rt.rt_flags = RTF_UP;
105	if (sin_addr(&rt.rt_gateway).s_addr)
106		rt.rt_flags |= RTF_GATEWAY;
107	if (sin_addr(&rt.rt_genmask).s_addr == INADDR_BROADCAST)
108		rt.rt_flags |= RTF_HOST;
109	rt.rt_dev = name;
110
111	/* Force address family to AF_INET */
112	rt.rt_dst.sa_family = AF_INET;
113	rt.rt_gateway.sa_family = AF_INET;
114	rt.rt_genmask.sa_family = AF_INET;
115
116	if (ioctl(s, cmd, &rt) < 0)
117		goto err;
118
119	close(s);
120	return 0;
121
122 err:
123	close(s);
124	perror(name);
125	return errno;
126}
127
128int
129route_add(char *name, int metric, char *dst, char *gateway, char *genmask)
130{
131	return route_manip(SIOCADDRT, name, metric, dst, gateway, genmask);
132}
133
134int
135route_del(char *name, int metric, char *dst, char *gateway, char *genmask)
136{
137	return route_manip(SIOCDELRT, name, metric, dst, gateway, genmask);
138}
139