Statistics
| Branch: | Revision:

root / net / tap-solaris.c @ 0389ced4

History | View | Annotate | Download (6.2 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
#include "sysemu.h"
27

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

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

    
48
    sbuf.maxlen = maxlen;
49
    sbuf.buf = (char *)buf;
50

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

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

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

    
72
    memset(&ifr, 0x0, sizeof(ifr));
73

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

    
80
    /* Check if IP device was opened */
81
    if( ip_fd )
82
       close(ip_fd);
83

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

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

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

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

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

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

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

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

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

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

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

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

    
158
    close (if_fd);
159

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

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

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

    
176
int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required)
177
{
178
    char  dev[10]="";
179
    int fd;
180
    if( (fd = tap_alloc(dev, sizeof(dev))) < 0 ){
181
       fprintf(stderr, "Cannot allocate TAP device\n");
182
       return -1;
183
    }
184
    pstrcpy(ifname, ifname_size, dev);
185
    if (*vnet_hdr) {
186
        /* Solaris doesn't have IFF_VNET_HDR */
187
        *vnet_hdr = 0;
188

    
189
        if (vnet_hdr_required && !*vnet_hdr) {
190
            error_report("vnet_hdr=1 requested, but no kernel "
191
                         "support for IFF_VNET_HDR available");
192
            close(fd);
193
            return -1;
194
        }
195
    }
196
    fcntl(fd, F_SETFL, O_NONBLOCK);
197
    return fd;
198
}
199

    
200
int tap_set_sndbuf(int fd, QemuOpts *opts)
201
{
202
    return 0;
203
}
204

    
205
int tap_probe_vnet_hdr(int fd)
206
{
207
    return 0;
208
}
209

    
210
int tap_probe_has_ufo(int fd)
211
{
212
    return 0;
213
}
214

    
215
int tap_probe_vnet_hdr_len(int fd, int len)
216
{
217
    return 0;
218
}
219

    
220
void tap_fd_set_vnet_hdr_len(int fd, int len)
221
{
222
}
223

    
224
void tap_fd_set_offload(int fd, int csum, int tso4,
225
                        int tso6, int ecn, int ufo)
226
{
227
}