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) | ... | ... |