Commit d5d10bc3056646404f4b60517b851398c3a28986
1 parent
80265918
Solaris tap device, by Sittichai Palingsong.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2429 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
150 additions
and
2 deletions
vl.c
... | ... | @@ -55,6 +55,21 @@ |
55 | 55 | #include <malloc.h> |
56 | 56 | #include <linux/rtc.h> |
57 | 57 | #include <linux/ppdev.h> |
58 | +#else | |
59 | +#include <sys/stat.h> | |
60 | +#include <sys/ethernet.h> | |
61 | +#include <sys/sockio.h> | |
62 | +#include <arpa/inet.h> | |
63 | +#include <netinet/arp.h> | |
64 | +#include <netinet/in.h> | |
65 | +#include <netinet/in_systm.h> | |
66 | +#include <netinet/ip.h> | |
67 | +#include <netinet/ip_icmp.h> // must come after ip.h | |
68 | +#include <netinet/udp.h> | |
69 | +#include <netinet/tcp.h> | |
70 | +#include <net/if.h> | |
71 | +#include <syslog.h> | |
72 | +#include <stropts.h> | |
58 | 73 | #endif |
59 | 74 | #endif |
60 | 75 | #endif |
... | ... | @@ -3199,7 +3214,15 @@ static void tap_send(void *opaque) |
3199 | 3214 | uint8_t buf[4096]; |
3200 | 3215 | int size; |
3201 | 3216 | |
3217 | +#ifdef __sun__ | |
3218 | + struct strbuf sbuf; | |
3219 | + int f = 0; | |
3220 | + sbuf.maxlen = sizeof(buf); | |
3221 | + sbuf.buf = buf; | |
3222 | + size = getmsg(s->fd, NULL, &sbuf, &f) >=0 ? sbuf.len : -1; | |
3223 | +#else | |
3202 | 3224 | size = read(s->fd, buf, sizeof(buf)); |
3225 | +#endif | |
3203 | 3226 | if (size > 0) { |
3204 | 3227 | qemu_send_packet(s->vc, buf, size); |
3205 | 3228 | } |
... | ... | @@ -3242,10 +3265,135 @@ static int tap_open(char *ifname, int ifname_size) |
3242 | 3265 | return fd; |
3243 | 3266 | } |
3244 | 3267 | #elif defined(__sun__) |
3268 | +#define TUNNEWPPA (('T'<<16) | 0x0001) | |
3269 | +/* | |
3270 | + * Allocate TAP device, returns opened fd. | |
3271 | + * Stores dev name in the first arg(must be large enough). | |
3272 | + */ | |
3273 | +int tap_alloc(char *dev) | |
3274 | +{ | |
3275 | + int tap_fd, if_fd, ppa = -1; | |
3276 | + static int ip_fd = 0; | |
3277 | + char *ptr; | |
3278 | + | |
3279 | + static int arp_fd = 0; | |
3280 | + int ip_muxid, arp_muxid; | |
3281 | + struct strioctl strioc_if, strioc_ppa; | |
3282 | + int link_type = I_PLINK;; | |
3283 | + struct lifreq ifr; | |
3284 | + char actual_name[32] = ""; | |
3285 | + | |
3286 | + memset(&ifr, 0x0, sizeof(ifr)); | |
3287 | + | |
3288 | + if( *dev ){ | |
3289 | + ptr = dev; | |
3290 | + while( *ptr && !isdigit((int)*ptr) ) ptr++; | |
3291 | + ppa = atoi(ptr); | |
3292 | + } | |
3293 | + | |
3294 | + /* Check if IP device was opened */ | |
3295 | + if( ip_fd ) | |
3296 | + close(ip_fd); | |
3297 | + | |
3298 | + if( (ip_fd = open("/dev/udp", O_RDWR, 0)) < 0){ | |
3299 | + syslog(LOG_ERR, "Can't open /dev/ip (actually /dev/udp)"); | |
3300 | + return -1; | |
3301 | + } | |
3302 | + | |
3303 | + if( (tap_fd = open("/dev/tap", O_RDWR, 0)) < 0){ | |
3304 | + syslog(LOG_ERR, "Can't open /dev/tap"); | |
3305 | + return -1; | |
3306 | + } | |
3307 | + | |
3308 | + /* Assign a new PPA and get its unit number. */ | |
3309 | + strioc_ppa.ic_cmd = TUNNEWPPA; | |
3310 | + strioc_ppa.ic_timout = 0; | |
3311 | + strioc_ppa.ic_len = sizeof(ppa); | |
3312 | + strioc_ppa.ic_dp = (char *)&ppa; | |
3313 | + if ((ppa = ioctl (tap_fd, I_STR, &strioc_ppa)) < 0) | |
3314 | + syslog (LOG_ERR, "Can't assign new interface"); | |
3315 | + | |
3316 | + if( (if_fd = open("/dev/tap", O_RDWR, 0)) < 0){ | |
3317 | + syslog(LOG_ERR, "Can't open /dev/tap (2)"); | |
3318 | + return -1; | |
3319 | + } | |
3320 | + if(ioctl(if_fd, I_PUSH, "ip") < 0){ | |
3321 | + syslog(LOG_ERR, "Can't push IP module"); | |
3322 | + return -1; | |
3323 | + } | |
3324 | + | |
3325 | + if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0) | |
3326 | + syslog(LOG_ERR, "Can't get flags\n"); | |
3327 | + | |
3328 | + snprintf (actual_name, 32, "tap%d", ppa); | |
3329 | + strncpy (ifr.lifr_name, actual_name, sizeof (ifr.lifr_name)); | |
3330 | + | |
3331 | + ifr.lifr_ppa = ppa; | |
3332 | + /* Assign ppa according to the unit number returned by tun device */ | |
3333 | + | |
3334 | + if (ioctl (if_fd, SIOCSLIFNAME, &ifr) < 0) | |
3335 | + syslog (LOG_ERR, "Can't set PPA %d", ppa); | |
3336 | + if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) <0) | |
3337 | + syslog (LOG_ERR, "Can't get flags\n"); | |
3338 | + /* Push arp module to if_fd */ | |
3339 | + if (ioctl (if_fd, I_PUSH, "arp") < 0) | |
3340 | + syslog (LOG_ERR, "Can't push ARP module (2)"); | |
3341 | + | |
3342 | + /* Push arp module to ip_fd */ | |
3343 | + if (ioctl (ip_fd, I_POP, NULL) < 0) | |
3344 | + syslog (LOG_ERR, "I_POP failed\n"); | |
3345 | + if (ioctl (ip_fd, I_PUSH, "arp") < 0) | |
3346 | + syslog (LOG_ERR, "Can't push ARP module (3)\n"); | |
3347 | + /* Open arp_fd */ | |
3348 | + if ((arp_fd = open ("/dev/tap", O_RDWR, 0)) < 0) | |
3349 | + syslog (LOG_ERR, "Can't open %s\n", "/dev/tap"); | |
3350 | + | |
3351 | + /* Set ifname to arp */ | |
3352 | + strioc_if.ic_cmd = SIOCSLIFNAME; | |
3353 | + strioc_if.ic_timout = 0; | |
3354 | + strioc_if.ic_len = sizeof(ifr); | |
3355 | + strioc_if.ic_dp = (char *)𝔦 | |
3356 | + if (ioctl(arp_fd, I_STR, &strioc_if) < 0){ | |
3357 | + syslog (LOG_ERR, "Can't set ifname to arp\n"); | |
3358 | + } | |
3359 | + | |
3360 | + if((ip_muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0){ | |
3361 | + syslog(LOG_ERR, "Can't link TAP device to IP"); | |
3362 | + return -1; | |
3363 | + } | |
3364 | + | |
3365 | + if ((arp_muxid = ioctl (ip_fd, link_type, arp_fd)) < 0) | |
3366 | + syslog (LOG_ERR, "Can't link TAP device to ARP"); | |
3367 | + | |
3368 | + close (if_fd); | |
3369 | + | |
3370 | + memset(&ifr, 0x0, sizeof(ifr)); | |
3371 | + strncpy (ifr.lifr_name, actual_name, sizeof (ifr.lifr_name)); | |
3372 | + ifr.lifr_ip_muxid = ip_muxid; | |
3373 | + ifr.lifr_arp_muxid = arp_muxid; | |
3374 | + | |
3375 | + if (ioctl (ip_fd, SIOCSLIFMUXID, &ifr) < 0) | |
3376 | + { | |
3377 | + ioctl (ip_fd, I_PUNLINK , arp_muxid); | |
3378 | + ioctl (ip_fd, I_PUNLINK, ip_muxid); | |
3379 | + syslog (LOG_ERR, "Can't set multiplexor id"); | |
3380 | + } | |
3381 | + | |
3382 | + sprintf(dev, "tap%d", ppa); | |
3383 | + return tap_fd; | |
3384 | +} | |
3385 | + | |
3245 | 3386 | static int tap_open(char *ifname, int ifname_size) |
3246 | 3387 | { |
3247 | - fprintf(stderr, "warning: tap_open not yet implemented\n"); | |
3248 | - return -1; | |
3388 | + char dev[10]=""; | |
3389 | + int fd; | |
3390 | + if( (fd = tap_alloc(dev)) < 0 ){ | |
3391 | + fprintf(stderr, "Cannot allocate TAP device\n"); | |
3392 | + return -1; | |
3393 | + } | |
3394 | + pstrcpy(ifname, ifname_size, dev); | |
3395 | + fcntl(fd, F_SETFL, O_NONBLOCK); | |
3396 | + return fd; | |
3249 | 3397 | } |
3250 | 3398 | #else |
3251 | 3399 | static int tap_open(char *ifname, int ifname_size) | ... | ... |