1cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike/* 2cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Licensed under the GPL 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <stdio.h> 7cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike#include <unistd.h> 8cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike#include <stdarg.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <errno.h> 10cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike#include <stddef.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <string.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sys/socket.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sys/wait.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "net_user.h" 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "os.h" 16c13e569073b89eb75216a2551e89ae93ad1f9951Paolo 'Blaisorblade' Giarrusso#include "um_malloc.h" 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint tap_open_common(void *dev, char *gate_addr) 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int tap_addr[4]; 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (gate_addr == NULL) 23108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return 0; 24cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], 25cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4) { 26cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike printk(UM_KERN_ERR "Invalid tap IP address - '%s'\n", 27cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike gate_addr); 28108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -EINVAL; 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 30108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return 0; 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33da00d9a5466558ccd9e7b7d04b13d7cb9160c876Jeff Dikevoid tap_check_ips(char *gate_addr, unsigned char *eth_addr) 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int tap_addr[4]; 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if ((gate_addr != NULL) && 38cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], 39cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) && 40cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike (eth_addr[0] == tap_addr[0]) && 41cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike (eth_addr[1] == tap_addr[1]) && 42cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike (eth_addr[2] == tap_addr[2]) && 43cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike (eth_addr[3] == tap_addr[3])) { 44cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike printk(UM_KERN_ERR "The tap IP address and the UML eth IP " 45cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike "address must be different\n"); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 49f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso/* Do reliable error handling as this fails frequently enough. */ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid read_output(int fd, char *output, int len) 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 52f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso int remain, ret, expected; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char c; 54f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso char *str; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 56cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (output == NULL) { 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds output = &c; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = sizeof(c); 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 60cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *output = '\0'; 62cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike ret = read(fd, &remain, sizeof(remain)); 63f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso 64f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso if (ret != sizeof(remain)) { 65cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (ret < 0) 66cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike ret = -errno; 67f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso expected = sizeof(remain); 68f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso str = "length"; 69f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso goto err; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 72cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike while (remain != 0) { 73f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso expected = (remain < len) ? remain : len; 74cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike ret = read(fd, output, expected); 75f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso if (ret != expected) { 76cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (ret < 0) 77cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike ret = -errno; 78f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso str = "data"; 79f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso goto err; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 81f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso remain -= ret; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 83f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 85f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso 86f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrussoerr: 87f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso if (ret < 0) 88cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike printk(UM_KERN_ERR "read_output - read of %s failed, " 89cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike "errno = %d\n", str, -ret); 90f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso else 91cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike printk(UM_KERN_ERR "read_output - read of %s failed, read only " 92cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike "%d of %d bytes\n", str, ret, expected); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint net_read(int fd, void *buf, int len) 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 99cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike n = read(fd, buf, len); 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 101cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if ((n < 0) && (errno == EAGAIN)) 102108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return 0; 103cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike else if (n == 0) 104108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -ENOTCONN; 105108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return n; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint net_recvfrom(int fd, void *buf, int len) 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1129ead6feedd28091d86cde0843be914847b4e10e8Jeff Dike CATCH_EINTR(n = recvfrom(fd, buf, len, 0, NULL, NULL)); 113cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (n < 0) { 114cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (errno == EAGAIN) 115108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return 0; 116108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -errno; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 118cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike else if (n == 0) 119108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -ENOTCONN; 120108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return n; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint net_write(int fd, void *buf, int len) 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 127cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike n = write(fd, buf, len); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 129cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if ((n < 0) && (errno == EAGAIN)) 130108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return 0; 131cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike else if (n == 0) 132108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -ENOTCONN; 133108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return n; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint net_send(int fd, void *buf, int len) 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1409ead6feedd28091d86cde0843be914847b4e10e8Jeff Dike CATCH_EINTR(n = send(fd, buf, len, 0)); 141cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (n < 0) { 142cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (errno == EAGAIN) 143108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return 0; 144108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -errno; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 146cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike else if (n == 0) 147108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -ENOTCONN; 148108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return n; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint net_sendto(int fd, void *buf, int len, void *to, int sock_len) 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1559ead6feedd28091d86cde0843be914847b4e10e8Jeff Dike CATCH_EINTR(n = sendto(fd, buf, len, 0, (struct sockaddr *) to, 1569ead6feedd28091d86cde0843be914847b4e10e8Jeff Dike sock_len)); 157cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (n < 0) { 158cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (errno == EAGAIN) 159108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return 0; 160108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -errno; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 162cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike else if (n == 0) 163108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -ENOTCONN; 164108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return n; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct change_pre_exec_data { 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int close_me; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int stdout; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void change_pre_exec(void *arg) 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct change_pre_exec_data *data = arg; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 176cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike close(data->close_me); 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dup2(data->stdout, 1); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int change_tramp(char **argv, char *output, int output_len) 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int pid, fds[2], err; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct change_pre_exec_data pe_data; 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = os_pipe(fds, 1, 0); 186cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (err < 0) { 187cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike printk(UM_KERN_ERR "change_tramp - pipe failed, err = %d\n", 188cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike -err); 189108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return err; 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pe_data.close_me = fds[0]; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pe_data.stdout = fds[1]; 193c43990162fc7f9d2f15a12797fdc6f9c0905f704Jeff Dike pid = run_helper(change_pre_exec, &pe_data, argv); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 195b1c332c9e813cbee6ca77c3a66ee4d312eb96770Paolo 'Blaisorblade' Giarrusso if (pid > 0) /* Avoid hang as we won't get data in failure case. */ 196b1c332c9e813cbee6ca77c3a66ee4d312eb96770Paolo 'Blaisorblade' Giarrusso read_output(fds[0], output, output_len); 197b1c332c9e813cbee6ca77c3a66ee4d312eb96770Paolo 'Blaisorblade' Giarrusso 198cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike close(fds[0]); 199cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike close(fds[1]); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pid > 0) 2021aa351a308d2c3ddb92b6cc45083fc54271d0010Jeff Dike helper_wait(pid); 203108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return pid; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void change(char *dev, char *what, unsigned char *addr, 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *netmask) 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char addr_buf[sizeof("255.255.255.255\0")]; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char netmask_buf[sizeof("255.255.255.255\0")]; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char version[sizeof("nnnnn\0")]; 212cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike char *argv[] = { "uml_net", version, what, dev, addr_buf, 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netmask_buf, NULL }; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *output; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int output_len, pid; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(version, "%d", UML_NET_VERSION); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); 219cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1], 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netmask[2], netmask[3]); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2221ffb9164f51094b7105ce9f81600b222ddf5b82cJeff Dike output_len = UM_KERN_PAGE_SIZE; 22343f5b3085fdd27c4edf535d938b2cb0ccead4f75Jeff Dike output = uml_kmalloc(output_len, UM_GFP_KERNEL); 224cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (output == NULL) 225cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike printk(UM_KERN_ERR "change : failed to allocate output " 226cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike "buffer\n"); 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pid = change_tramp(argv, output, output_len); 229fbee8d933c775cdb9daac3063659cda38c1776c2Vitaliy Ivanov if (pid < 0) { 230fbee8d933c775cdb9daac3063659cda38c1776c2Vitaliy Ivanov kfree(output); 231fbee8d933c775cdb9daac3063659cda38c1776c2Vitaliy Ivanov return; 232fbee8d933c775cdb9daac3063659cda38c1776c2Vitaliy Ivanov } 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 234cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (output != NULL) { 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s", output); 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(output); 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid open_addr(unsigned char *addr, unsigned char *netmask, void *arg) 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds change(arg, "add", addr, netmask); 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid close_addr(unsigned char *addr, unsigned char *netmask, void *arg) 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds change(arg, "del", addr, netmask); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldschar *split_if_spec(char *str, ...) 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char **arg, *end; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds va_list ap; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds va_start(ap, str); 256cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike while ((arg = va_arg(ap, char **)) != NULL) { 257cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (*str == '\0') 258108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return NULL; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = strchr(str, ','); 260cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (end != str) 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *arg = str; 262cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (end == NULL) 263108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return NULL; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *end++ = '\0'; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds str = end; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds va_end(ap); 268108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return str; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 270