~ubuntu-branches/ubuntu/raring/uml-utilities/raring

« back to all changes in this revision

Viewing changes to uml_net/tuntap.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2004-04-14 17:59:45 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040414175945-olq69xkt2da1oxca
Tags: 20040406-1
* New upstream release
* Patch from Carlos Perelló Marín to fix uml_proxy_arp with multiple
  addresses (Closes: #243834)

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
#include "host.h"
18
18
#include "output.h"
19
19
 
20
 
static void tuntap_up(int fd, char *gate_addr)
 
20
static int do_tuntap_up(char *gate_addr, struct output *output, 
 
21
                        struct ifreq *ifr)
 
22
{
 
23
  int tap_fd;
 
24
  char *ifconfig_argv[] = { "ifconfig", ifr->ifr_name, gate_addr, "netmask", 
 
25
                            "255.255.255.255", "up", NULL };
 
26
  char *insmod_argv[] = { "modprobe", "tun", NULL };
 
27
 
 
28
  if(setreuid(0, 0) < 0){
 
29
    output_errno(output, "setreuid to root failed : ");
 
30
    return(-1);
 
31
  }
 
32
 
 
33
  /* XXX hardcoded dir name and perms */
 
34
  umask(0);
 
35
  mkdir("/dev/net", 0755);
 
36
 
 
37
  /* #includes for MISC_MAJOR and TUN_MINOR bomb in userspace */
 
38
  mk_node("/dev/net/tun", 10, 200);
 
39
 
 
40
  do_exec(insmod_argv, 0, output);
 
41
  
 
42
  if((tap_fd = open("/dev/net/tun", O_RDWR)) < 0){
 
43
    output_errno(output, "Opening /dev/net/tun failed : ");
 
44
    return(-1);
 
45
  }
 
46
  memset(ifr, 0, sizeof(*ifr));
 
47
  ifr->ifr_flags = IFF_TAP | IFF_NO_PI;
 
48
  ifr->ifr_name[0] = '\0';
 
49
  if(ioctl(tap_fd, TUNSETIFF, (void *) ifr) < 0){
 
50
    output_errno(output, "TUNSETIFF : ");
 
51
    return(-1);
 
52
  }
 
53
 
 
54
  if((*gate_addr != '\0') && do_exec(ifconfig_argv, 1, output))
 
55
    return(-1);
 
56
  forward_ip(output);
 
57
  return(tap_fd);
 
58
}
 
59
 
 
60
static void tuntap_up(int fd, int argc, char **argv)
21
61
{
22
62
  struct ifreq ifr;
23
 
  int tap_fd, *fd_ptr;
24
 
  char anc[CMSG_SPACE(sizeof(tap_fd))];
25
63
  struct msghdr msg;
26
64
  struct cmsghdr *cmsg;
27
 
  char *ifconfig_argv[] = { "ifconfig", ifr.ifr_name, gate_addr, "netmask", 
28
 
                            "255.255.255.255", "up", NULL };
29
 
  char *insmod_argv[] = { "insmod", "tun", NULL };
30
65
  struct output output = INIT_OUTPUT;
31
66
  struct iovec iov[2];
32
 
  int retval;
 
67
  int tap_fd, *fd_ptr;
 
68
  char anc[CMSG_SPACE(sizeof(tap_fd))];
 
69
  char *gate_addr;
33
70
 
34
71
  msg.msg_control = NULL;
35
72
  msg.msg_controllen = 0;
37
74
  iov[0].iov_base = NULL;
38
75
  iov[0].iov_len = 0;
39
76
 
40
 
  if(setreuid(0, 0) < 0){
41
 
    output_errno(&output, "setreuid to root failed : ");
42
 
    goto out;
43
 
  }
44
 
 
45
 
  /* XXX hardcoded dir name and perms */
46
 
  umask(0);
47
 
  retval = mkdir("/dev/net", 0755);
48
 
 
49
 
  /* #includes for MISC_MAJOR and TUN_MINOR bomb in userspace */
50
 
  mk_node("/dev/net/tun", 10, 200);
51
 
 
52
 
  do_exec(insmod_argv, 0, &output);
53
 
  
54
 
  if((tap_fd = open("/dev/net/tun", O_RDWR)) < 0){
55
 
    output_errno(&output, "Opening /dev/net/tun failed : ");
56
 
    goto out;
57
 
  }
58
 
  memset(&ifr, 0, sizeof(ifr));
59
 
  ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
60
 
  ifr.ifr_name[0] = '\0';
61
 
  if(ioctl(tap_fd, TUNSETIFF, (void *) &ifr) < 0){
62
 
    output_errno(&output, "TUNSETIFF : ");
63
 
    goto out;
64
 
  }
65
 
 
66
 
  if((*gate_addr != '\0') && do_exec(ifconfig_argv, 1, &output)) goto out;
67
 
  forward_ip(&output);
68
 
 
69
 
  iov[0].iov_base = ifr.ifr_name;
70
 
  iov[0].iov_len = IFNAMSIZ;
71
 
 
72
 
  msg.msg_control = anc;
73
 
  msg.msg_controllen = sizeof(anc);
74
 
  
75
 
  cmsg = CMSG_FIRSTHDR(&msg);
76
 
  cmsg->cmsg_level = SOL_SOCKET;
77
 
  cmsg->cmsg_type = SCM_RIGHTS;
78
 
  cmsg->cmsg_len = CMSG_LEN(sizeof(tap_fd));
79
 
 
80
 
  msg.msg_controllen = cmsg->cmsg_len;
81
 
 
82
 
  fd_ptr = (int *) CMSG_DATA(cmsg);
83
 
  *fd_ptr = tap_fd;
 
77
  if(argc < 1){
 
78
    add_output(&output, "Too few arguments to tuntap_up\n", -1);
 
79
    goto out;
 
80
  }
 
81
 
 
82
  gate_addr = argv[0];
 
83
  if((tap_fd = do_tuntap_up(gate_addr, &output, &ifr)) > 0){
 
84
    iov[0].iov_base = ifr.ifr_name;
 
85
    iov[0].iov_len = IFNAMSIZ;
 
86
 
 
87
    msg.msg_control = anc;
 
88
    msg.msg_controllen = sizeof(anc);
 
89
  
 
90
    cmsg = CMSG_FIRSTHDR(&msg);
 
91
    cmsg->cmsg_level = SOL_SOCKET;
 
92
    cmsg->cmsg_type = SCM_RIGHTS;
 
93
    cmsg->cmsg_len = CMSG_LEN(sizeof(tap_fd));
 
94
 
 
95
    msg.msg_controllen = cmsg->cmsg_len;
 
96
 
 
97
    fd_ptr = (int *) CMSG_DATA(cmsg);
 
98
    *fd_ptr = tap_fd;
 
99
  }
84
100
 
85
101
 out:
86
102
  iov[1].iov_base = output.buffer;
102
118
{
103
119
  char *op = argv[0];
104
120
 
105
 
  if(!strcmp(op, "up")) tuntap_up(atoi(argv[2]), argv[3]);
 
121
  if(!strcmp(op, "up")) tuntap_up(atoi(argv[2]), argc - 3, argv + 3);
106
122
  else if(!strcmp(op, "add") || !strcmp(op, "del"))
107
123
    change_addr(argv[1], argv[2], argv[3], NULL, NULL);
108
124
  else {
116
132
  char *op = argv[0];
117
133
  struct output output = INIT_OUTPUT;
118
134
 
119
 
  if(!strcmp(op, "up")) tuntap_up(1, argv[2]);
 
135
  if(!strcmp(op, "up")) tuntap_up(1, argc - 2, argv + 2);
120
136
  else if(!strcmp(op, "add") || !strcmp(op, "del"))
121
137
    change_addr(op, argv[1], argv[2], NULL, &output);
122
138
  else {
128
144
 
129
145
void tuntap_v4(int argc, char **argv)
130
146
{
131
 
  char *op = argv[0];
 
147
  char *op;
132
148
  struct output output = INIT_OUTPUT;
133
149
 
134
 
  if(!strcmp(op, "up")) tuntap_up(1, argv[1]);
135
 
  else if(!strcmp(op, "add") || !strcmp(op, "del"))
136
 
    change_addr(op, argv[1], argv[2], argv[3], &output);
 
150
  if(argc < 1){
 
151
    add_output(&output, "uml_net : too few arguments to tuntap_v4\n", -1);
 
152
    write_output(1, &output);
 
153
    exit(1);
 
154
  }
 
155
  op = argv[0];
 
156
  if(!strcmp(op, "up")) tuntap_up(1, argc - 1, argv + 1);
 
157
  else if(!strcmp(op, "add") || !strcmp(op, "del")){
 
158
    if(argc < 4)
 
159
      add_output(&output, "uml_net : too few arguments to tuntap "
 
160
                 "change_addr\n", -1);
 
161
    else change_addr(op, argv[1], argv[2], argv[3], &output);
 
162
    write_output(1, &output);
 
163
  }
137
164
  else {
138
165
    fprintf(stderr, "Bad tuntap op : '%s'\n", op);
139
166
    exit(1);
140
167
  }
141
 
  write_output(1, &output);
142
168
}
143
169