Statistics
| Branch: | Revision:

root / net / tap-solaris.c @ 15ac913b

History | View | Annotate | Download (5.5 kB)

1
/*
2
 * QEMU System Emulator
3
 *
4
 * Copyright (c) 2003-2008 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24

    
25
#include "net/tap.h"
26

    
27
#include <sys/stat.h>
28
#include <sys/ethernet.h>
29
#include <sys/sockio.h>
30
#include <netinet/arp.h>
31
#include <netinet/in.h>
32
#include <netinet/in_systm.h>
33
#include <netinet/ip.h>
34
#include <netinet/ip_icmp.h> // must come after ip.h
35
#include <netinet/udp.h>
36
#include <netinet/tcp.h>
37
#include <net/if.h>
38
#include <syslog.h>
39
#include <stropts.h>
40

    
41
ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen)
42
{
43
    struct strbuf sbuf;
44
    int f = 0;
45

    
46
    sbuf.maxlen = maxlen;
47
    sbuf.buf = (char *)buf;
48

    
49
    return getmsg(tapfd, NULL, &sbuf, &f) >= 0 ? sbuf.len : -1;
50
}
51

    
52
#define TUNNEWPPA       (('T'<<16) | 0x0001)
53
/*
54
 * Allocate TAP device, returns opened fd.
55
 * Stores dev name in the first arg(must be large enough).
56
 */
57
static int tap_alloc(char *dev, size_t dev_size)
58
{
59
    int tap_fd, if_fd, ppa = -1;
60
    static int ip_fd = 0;
61
    char *ptr;
62

    
63
    static int arp_fd = 0;
64
    int ip_muxid, arp_muxid;
65
    struct strioctl  strioc_if, strioc_ppa;
66
    int link_type = I_PLINK;;
67
    struct lifreq ifr;
68
    char actual_name[32] = "";
69

    
70
    memset(&ifr, 0x0, sizeof(ifr));
71

    
72
    if( *dev ){
73
       ptr = dev;
74
       while( *ptr && !qemu_isdigit((int)*ptr) ) ptr++;
75
       ppa = atoi(ptr);
76
    }
77

    
78
    /* Check if IP device was opened */
79
    if( ip_fd )
80
       close(ip_fd);
81

    
82
    TFR(ip_fd = open("/dev/udp", O_RDWR, 0));
83
    if (ip_fd < 0) {
84
       syslog(LOG_ERR, "Can't open /dev/ip (actually /dev/udp)");
85
       return -1;
86
    }
87

    
88
    TFR(tap_fd = open("/dev/tap", O_RDWR, 0));
89
    if (tap_fd < 0) {
90
       syslog(LOG_ERR, "Can't open /dev/tap");
91
       return -1;
92
    }
93

    
94
    /* Assign a new PPA and get its unit number. */
95
    strioc_ppa.ic_cmd = TUNNEWPPA;
96
    strioc_ppa.ic_timout = 0;
97
    strioc_ppa.ic_len = sizeof(ppa);
98
    strioc_ppa.ic_dp = (char *)&ppa;
99
    if ((ppa = ioctl (tap_fd, I_STR, &strioc_ppa)) < 0)
100
       syslog (LOG_ERR, "Can't assign new interface");
101

    
102
    TFR(if_fd = open("/dev/tap", O_RDWR, 0));
103
    if (if_fd < 0) {
104
       syslog(LOG_ERR, "Can't open /dev/tap (2)");
105
       return -1;
106
    }
107
    if(ioctl(if_fd, I_PUSH, "ip") < 0){
108
       syslog(LOG_ERR, "Can't push IP module");
109
       return -1;
110
    }
111

    
112
    if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0)
113
        syslog(LOG_ERR, "Can't get flags\n");
114

    
115
    snprintf (actual_name, 32, "tap%d", ppa);
116
    pstrcpy(ifr.lifr_name, sizeof(ifr.lifr_name), actual_name);
117

    
118
    ifr.lifr_ppa = ppa;
119
    /* Assign ppa according to the unit number returned by tun device */
120

    
121
    if (ioctl (if_fd, SIOCSLIFNAME, &ifr) < 0)
122
        syslog (LOG_ERR, "Can't set PPA %d", ppa);
123
    if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) <0)
124
        syslog (LOG_ERR, "Can't get flags\n");
125
    /* Push arp module to if_fd */
126
    if (ioctl (if_fd, I_PUSH, "arp") < 0)
127
        syslog (LOG_ERR, "Can't push ARP module (2)");
128

    
129
    /* Push arp module to ip_fd */
130
    if (ioctl (ip_fd, I_POP, NULL) < 0)
131
        syslog (LOG_ERR, "I_POP failed\n");
132
    if (ioctl (ip_fd, I_PUSH, "arp") < 0)
133
        syslog (LOG_ERR, "Can't push ARP module (3)\n");
134
    /* Open arp_fd */
135
    TFR(arp_fd = open ("/dev/tap", O_RDWR, 0));
136
    if (arp_fd < 0)
137
       syslog (LOG_ERR, "Can't open %s\n", "/dev/tap");
138

    
139
    /* Set ifname to arp */
140
    strioc_if.ic_cmd = SIOCSLIFNAME;
141
    strioc_if.ic_timout = 0;
142
    strioc_if.ic_len = sizeof(ifr);
143
    strioc_if.ic_dp = (char *)&ifr;
144
    if (ioctl(arp_fd, I_STR, &strioc_if) < 0){
145
        syslog (LOG_ERR, "Can't set ifname to arp\n");
146
    }
147

    
148
    if((ip_muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0){
149
       syslog(LOG_ERR, "Can't link TAP device to IP");
150
       return -1;
151
    }
152

    
153
    if ((arp_muxid = ioctl (ip_fd, link_type, arp_fd)) < 0)
154
        syslog (LOG_ERR, "Can't link TAP device to ARP");
155

    
156
    close (if_fd);
157

    
158
    memset(&ifr, 0x0, sizeof(ifr));
159
    pstrcpy(ifr.lifr_name, sizeof(ifr.lifr_name), actual_name);
160
    ifr.lifr_ip_muxid  = ip_muxid;
161
    ifr.lifr_arp_muxid = arp_muxid;
162

    
163
    if (ioctl (ip_fd, SIOCSLIFMUXID, &ifr) < 0)
164
    {
165
      ioctl (ip_fd, I_PUNLINK , arp_muxid);
166
      ioctl (ip_fd, I_PUNLINK, ip_muxid);
167
      syslog (LOG_ERR, "Can't set multiplexor id");
168
    }
169

    
170
    snprintf(dev, dev_size, "tap%d", ppa);
171
    return tap_fd;
172
}
173

    
174
int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required)
175
{
176
    char  dev[10]="";
177
    int fd;
178
    if( (fd = tap_alloc(dev, sizeof(dev))) < 0 ){
179
       fprintf(stderr, "Cannot allocate TAP device\n");
180
       return -1;
181
    }
182
    pstrcpy(ifname, ifname_size, dev);
183
    fcntl(fd, F_SETFL, O_NONBLOCK);
184
    return fd;
185
}
186

    
187
int tap_set_sndbuf(int fd, QemuOpts *opts)
188
{
189
    return 0;
190
}