1 /*
2  * ARAnyM ethernet networking: ifconfig
3  *
4  * made by extreme stripping of unnecessary code in standard ifconfig
5  *
6  * Standa and Joy of ARAnyM team in 03/2003 (C) 2003-2007
7  *
8  */
9 
10 /*
11  * ifconfig   This file contains an implementation of the command
12  *              that either displays or sets the characteristics of
13  *              one or more of the system's networking interfaces.
14  *
15  * Author:      Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
16  *              and others.  Copyright 1993 MicroWalt Corporation
17  *
18  *              This program is free software; you can redistribute it
19  *              and/or  modify it under  the terms of  the GNU General
20  *              Public  License as  published  by  the  Free  Software
21  *              Foundation;  either  version 2 of the License, or  (at
22  *              your option) any later version.
23  *
24  * Patched to support 'add' and 'del' keywords for INET(4) addresses
25  * by Mrs. Brisby <mrs.brisby@nimh.org>
26  *
27  * {1.34} - 19980630 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
28  *                     - gettext instead of catgets for i18n
29  *          10/1998  - Andi Kleen. Use interface list primitives.
30  *	    20001008 - Bernd Eckenfels, Patch from RH for setting mtu
31  *			(default AF was wrong)
32  *          20010404 - Arnaldo Carvalho de Melo, use setlocale
33  */
34 
35 #ifdef __linux__
36 #include "linux/libcwrap.h"
37 #endif
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <sys/ioctl.h>
41 #include <netinet/in.h>
42 #include <net/if.h>
43 #include <net/if_arp.h>
44 #include <arpa/inet.h>
45 #include <stdio.h>
46 #include <errno.h>
47 #include <fcntl.h>
48 #include <ctype.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52 #include <netdb.h>
53 
54 static int skfd;
55 
56 /* Like strncpy but make sure the resulting string is always 0 terminated. */
safe_strncpy(char * dst,const char * src,size_t size)57 static char *safe_strncpy(char *dst, const char *src, size_t size)
58 {
59     dst[size-1] = '\0';
60     return strncpy(dst,src,size-1);
61 }
62 
set_ip_using(const char * name,unsigned long c,const char * ip,const char * text)63 static int set_ip_using(const char *name, unsigned long c, const char *ip, const char *text)
64 {
65     struct ifreq ifr;
66     struct sockaddr_in sin;
67     char host[128];
68 
69     memset(&ifr, 0, sizeof(ifr));
70     safe_strncpy(ifr.ifr_name, name, IFNAMSIZ);
71     memset(&sin, 0, sizeof(sin));
72     sin.sin_family = AF_INET;
73 	safe_strncpy(host, ip, (sizeof host));
74     if (! inet_aton(host, &sin.sin_addr)) {
75 		fprintf(stderr, "%s '%s' invalid\n", text, ip);
76     	return 1;
77     }
78 
79     if (c == SIOCSIFADDR)
80     	memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr));
81     else if (c == SIOCSIFDSTADDR)
82     	memcpy(&ifr.ifr_dstaddr, &sin, sizeof(struct sockaddr));
83     else if (c == SIOCSIFNETMASK)
84 #ifdef OS_darwin
85     	memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr));
86 #else
87 		memcpy(&ifr.ifr_netmask, &sin, sizeof(struct sockaddr));
88 #endif
89     else
90     	return 2;
91 
92     if (ioctl(skfd, c, &ifr) < 0) {
93     	perror(text);
94 		return -1;
95 	}
96     return 0;
97 }
98 
set_mtu(const char * name,int mtu_size)99 int set_mtu(const char *name, int mtu_size)
100 {
101     struct ifreq ifr;
102 
103     memset(&ifr, 0, sizeof(ifr));
104     safe_strncpy(ifr.ifr_name, name, IFNAMSIZ);
105 	ifr.ifr_mtu = mtu_size;
106 	if (ioctl(skfd, SIOCSIFMTU, &ifr) < 0) {
107 		perror("SIOCSIFMTU");
108 		return -1;
109 	}
110 	return 0;
111 }
112 
113 /* Set a certain interface flag. */
set_flag(const char * name,short flag)114 static int set_flag(const char *name, short flag)
115 {
116     struct ifreq ifr;
117 
118     memset(&ifr, 0, sizeof(ifr));
119     safe_strncpy(ifr.ifr_name, name, IFNAMSIZ);
120     if (ioctl (skfd, SIOCGIFFLAGS, &ifr) < 0) {
121 		perror("SIOCGIFFLAGS");
122 		return -1;
123     }
124     ifr.ifr_flags |= flag;
125     if (ioctl(skfd, SIOCSIFFLAGS, &ifr) < 0) {
126 		perror("SIOCSIFFLAGS");
127 		return -2;
128     }
129     return 0;
130 }
131 
main(int argc,char ** argv)132 int main(int argc, char **argv)
133 {
134     const char *device;
135 
136     if (argc != 6) {
137     	fprintf(stderr, "Usage: %s tap_device host_IP atari_IP netmask mtu_size\n", argv[0]);
138     	return -1;
139     }
140 
141     device = argv[1];
142 
143     /* Make sure this is a tap device - don't allow messing with other
144      * interfaces. Poor security is better than none. */
145     if (strncmp(device, "tap", 3)) {
146     	fprintf(stderr, "%s designed for tap devices only\n", argv[0]);
147     }
148 
149     /* Create a channel to the NET kernel. */
150     if ((skfd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {
151 		perror("socket");
152 		return 1;
153     }
154 
155 	/* Set Host IP */
156 	if (set_ip_using(device, SIOCSIFADDR, argv[2], "host_IP")) {
157 		return 2;
158    	}
159 
160     /* Set Atari IP */
161 	if (set_ip_using(device, SIOCSIFDSTADDR, argv[3], "atari_IP")) {
162 		return 3;
163    	}
164 
165     /* Set Netmask */
166     if (set_ip_using(device, SIOCSIFNETMASK, argv[4], "netmask")) {
167 		return 4;
168     }
169 
170 	/* Set MTU */
171 	if (set_mtu(device, atoi(argv[5]))) {
172 		return 5;
173 	}
174 
175 	/* Set Point-to-point flag and put it up */
176     if (set_flag(device, IFF_UP | IFF_RUNNING | IFF_POINTOPOINT)) {
177     	return 6;
178     }
179 
180 	return 0;
181 }
182