net_user.c revision 1aa351a308d2c3ddb92b6cc45083fc54271d0010
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" 15cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike#include "kern_constants.h" 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "os.h" 17c13e569073b89eb75216a2551e89ae93ad1f9951Paolo 'Blaisorblade' Giarrusso#include "um_malloc.h" 18cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike#include "user.h" 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint tap_open_common(void *dev, char *gate_addr) 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int tap_addr[4]; 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (gate_addr == NULL) 25108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return 0; 26cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], 27cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4) { 28cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike printk(UM_KERN_ERR "Invalid tap IP address - '%s'\n", 29cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike gate_addr); 30108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -EINVAL; 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 32108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return 0; 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35da00d9a5466558ccd9e7b7d04b13d7cb9160c876Jeff Dikevoid tap_check_ips(char *gate_addr, unsigned char *eth_addr) 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int tap_addr[4]; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if ((gate_addr != NULL) && 40cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], 41cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) && 42cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike (eth_addr[0] == tap_addr[0]) && 43cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike (eth_addr[1] == tap_addr[1]) && 44cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike (eth_addr[2] == tap_addr[2]) && 45cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike (eth_addr[3] == tap_addr[3])) { 46cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike printk(UM_KERN_ERR "The tap IP address and the UML eth IP " 47cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike "address must be different\n"); 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso/* Do reliable error handling as this fails frequently enough. */ 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid read_output(int fd, char *output, int len) 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 54f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso int remain, ret, expected; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char c; 56f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso char *str; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 58cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (output == NULL) { 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds output = &c; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = sizeof(c); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 62cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *output = '\0'; 64cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike ret = read(fd, &remain, sizeof(remain)); 65f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso 66f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso if (ret != sizeof(remain)) { 67cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (ret < 0) 68cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike ret = -errno; 69f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso expected = sizeof(remain); 70f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso str = "length"; 71f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso goto err; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 74cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike while (remain != 0) { 75f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso expected = (remain < len) ? remain : len; 76cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike ret = read(fd, output, expected); 77f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso if (ret != expected) { 78cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (ret < 0) 79cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike ret = -errno; 80f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso str = "data"; 81f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso goto err; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 83f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso remain -= ret; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 85f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 87f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso 88f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrussoerr: 89f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso if (ret < 0) 90cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike printk(UM_KERN_ERR "read_output - read of %s failed, " 91cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike "errno = %d\n", str, -ret); 92f462e8f913bdc7a28ce55508d0c045a0c445b157Paolo 'Blaisorblade' Giarrusso else 93cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike printk(UM_KERN_ERR "read_output - read of %s failed, read only " 94cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike "%d of %d bytes\n", str, ret, expected); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint net_read(int fd, void *buf, int len) 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 101cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike n = read(fd, buf, len); 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 103cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if ((n < 0) && (errno == EAGAIN)) 104108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return 0; 105cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike else if (n == 0) 106108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -ENOTCONN; 107108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return n; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint net_recvfrom(int fd, void *buf, int len) 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1149ead6feedd28091d86cde0843be914847b4e10e8Jeff Dike CATCH_EINTR(n = recvfrom(fd, buf, len, 0, NULL, NULL)); 115cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (n < 0) { 116cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (errno == EAGAIN) 117108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return 0; 118108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -errno; 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 120cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike else if (n == 0) 121108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -ENOTCONN; 122108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return n; 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint net_write(int fd, void *buf, int len) 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 129cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike n = write(fd, buf, len); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if ((n < 0) && (errno == EAGAIN)) 132108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return 0; 133cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike else if (n == 0) 134108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -ENOTCONN; 135108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return n; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint net_send(int fd, void *buf, int len) 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1429ead6feedd28091d86cde0843be914847b4e10e8Jeff Dike CATCH_EINTR(n = send(fd, buf, len, 0)); 143cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (n < 0) { 144cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (errno == EAGAIN) 145108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return 0; 146108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -errno; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 148cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike else if (n == 0) 149108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -ENOTCONN; 150108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return n; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint net_sendto(int fd, void *buf, int len, void *to, int sock_len) 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int n; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1579ead6feedd28091d86cde0843be914847b4e10e8Jeff Dike CATCH_EINTR(n = sendto(fd, buf, len, 0, (struct sockaddr *) to, 1589ead6feedd28091d86cde0843be914847b4e10e8Jeff Dike sock_len)); 159cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (n < 0) { 160cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (errno == EAGAIN) 161108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return 0; 162108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -errno; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 164cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike else if (n == 0) 165108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return -ENOTCONN; 166108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return n; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct change_pre_exec_data { 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int close_me; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int stdout; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void change_pre_exec(void *arg) 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct change_pre_exec_data *data = arg; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 178cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike close(data->close_me); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dup2(data->stdout, 1); 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int change_tramp(char **argv, char *output, int output_len) 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int pid, fds[2], err; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct change_pre_exec_data pe_data; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = os_pipe(fds, 1, 0); 188cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (err < 0) { 189cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike printk(UM_KERN_ERR "change_tramp - pipe failed, err = %d\n", 190cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike -err); 191108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return err; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pe_data.close_me = fds[0]; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pe_data.stdout = fds[1]; 195c43990162fc7f9d2f15a12797fdc6f9c0905f704Jeff Dike pid = run_helper(change_pre_exec, &pe_data, argv); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 197b1c332c9e813cbee6ca77c3a66ee4d312eb96770Paolo 'Blaisorblade' Giarrusso if (pid > 0) /* Avoid hang as we won't get data in failure case. */ 198b1c332c9e813cbee6ca77c3a66ee4d312eb96770Paolo 'Blaisorblade' Giarrusso read_output(fds[0], output, output_len); 199b1c332c9e813cbee6ca77c3a66ee4d312eb96770Paolo 'Blaisorblade' Giarrusso 200cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike close(fds[0]); 201cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike close(fds[1]); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pid > 0) 2041aa351a308d2c3ddb92b6cc45083fc54271d0010Jeff Dike helper_wait(pid); 205108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return pid; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void change(char *dev, char *what, unsigned char *addr, 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *netmask) 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char addr_buf[sizeof("255.255.255.255\0")]; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char netmask_buf[sizeof("255.255.255.255\0")]; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char version[sizeof("nnnnn\0")]; 214cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike char *argv[] = { "uml_net", version, what, dev, addr_buf, 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netmask_buf, NULL }; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *output; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int output_len, pid; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(version, "%d", UML_NET_VERSION); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); 221cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1], 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netmask[2], netmask[3]); 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241ffb9164f51094b7105ce9f81600b222ddf5b82cJeff Dike output_len = UM_KERN_PAGE_SIZE; 225e4c4bf9968cb4f0fceb1b8fb54790ccae73caf4eJeff Dike output = kmalloc(output_len, UM_GFP_KERNEL); 226cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (output == NULL) 227cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike printk(UM_KERN_ERR "change : failed to allocate output " 228cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike "buffer\n"); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pid = change_tramp(argv, output, output_len); 231cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (pid < 0) return; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 233cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (output != NULL) { 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s", output); 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(output); 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid open_addr(unsigned char *addr, unsigned char *netmask, void *arg) 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds change(arg, "add", addr, netmask); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid close_addr(unsigned char *addr, unsigned char *netmask, void *arg) 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds change(arg, "del", addr, netmask); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldschar *split_if_spec(char *str, ...) 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char **arg, *end; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds va_list ap; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds va_start(ap, str); 255cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike while ((arg = va_arg(ap, char **)) != NULL) { 256cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (*str == '\0') 257108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return NULL; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = strchr(str, ','); 259cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (end != str) 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *arg = str; 261cd1ae0e49bdd814cfaa2e5ab28cff21a30e20085Jeff Dike if (end == NULL) 262108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return NULL; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *end++ = '\0'; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds str = end; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds va_end(ap); 267108ffa8cbfa323d462a2f4b49f38da3205d36e5aJeff Dike return str; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 269