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