diff options
Diffstat (limited to 'Documentation/lguest/lguest.c')
-rw-r--r-- | Documentation/lguest/lguest.c | 122 |
1 files changed, 89 insertions, 33 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c index 686e2d435c75..684d61191bee 100644 --- a/Documentation/lguest/lguest.c +++ b/Documentation/lguest/lguest.c | |||
@@ -1265,10 +1265,25 @@ static void setup_console(void) | |||
1265 | 1265 | ||
1266 | static u32 str2ip(const char *ipaddr) | 1266 | static u32 str2ip(const char *ipaddr) |
1267 | { | 1267 | { |
1268 | unsigned int byte[4]; | 1268 | unsigned int b[4]; |
1269 | 1269 | ||
1270 | sscanf(ipaddr, "%u.%u.%u.%u", &byte[0], &byte[1], &byte[2], &byte[3]); | 1270 | if (sscanf(ipaddr, "%u.%u.%u.%u", &b[0], &b[1], &b[2], &b[3]) != 4) |
1271 | return (byte[0] << 24) | (byte[1] << 16) | (byte[2] << 8) | byte[3]; | 1271 | errx(1, "Failed to parse IP address '%s'", ipaddr); |
1272 | return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; | ||
1273 | } | ||
1274 | |||
1275 | static void str2mac(const char *macaddr, unsigned char mac[6]) | ||
1276 | { | ||
1277 | unsigned int m[6]; | ||
1278 | if (sscanf(macaddr, "%02x:%02x:%02x:%02x:%02x:%02x", | ||
1279 | &m[0], &m[1], &m[2], &m[3], &m[4], &m[5]) != 6) | ||
1280 | errx(1, "Failed to parse mac address '%s'", macaddr); | ||
1281 | mac[0] = m[0]; | ||
1282 | mac[1] = m[1]; | ||
1283 | mac[2] = m[2]; | ||
1284 | mac[3] = m[3]; | ||
1285 | mac[4] = m[4]; | ||
1286 | mac[5] = m[5]; | ||
1272 | } | 1287 | } |
1273 | 1288 | ||
1274 | /* This code is "adapted" from libbridge: it attaches the Host end of the | 1289 | /* This code is "adapted" from libbridge: it attaches the Host end of the |
@@ -1289,6 +1304,7 @@ static void add_to_bridge(int fd, const char *if_name, const char *br_name) | |||
1289 | errx(1, "interface %s does not exist!", if_name); | 1304 | errx(1, "interface %s does not exist!", if_name); |
1290 | 1305 | ||
1291 | strncpy(ifr.ifr_name, br_name, IFNAMSIZ); | 1306 | strncpy(ifr.ifr_name, br_name, IFNAMSIZ); |
1307 | ifr.ifr_name[IFNAMSIZ-1] = '\0'; | ||
1292 | ifr.ifr_ifindex = ifidx; | 1308 | ifr.ifr_ifindex = ifidx; |
1293 | if (ioctl(fd, SIOCBRADDIF, &ifr) < 0) | 1309 | if (ioctl(fd, SIOCBRADDIF, &ifr) < 0) |
1294 | err(1, "can't add %s to bridge %s", if_name, br_name); | 1310 | err(1, "can't add %s to bridge %s", if_name, br_name); |
@@ -1297,58 +1313,80 @@ static void add_to_bridge(int fd, const char *if_name, const char *br_name) | |||
1297 | /* This sets up the Host end of the network device with an IP address, brings | 1313 | /* This sets up the Host end of the network device with an IP address, brings |
1298 | * it up so packets will flow, the copies the MAC address into the hwaddr | 1314 | * it up so packets will flow, the copies the MAC address into the hwaddr |
1299 | * pointer. */ | 1315 | * pointer. */ |
1300 | static void configure_device(int fd, const char *devname, u32 ipaddr, | 1316 | static void configure_device(int fd, const char *tapif, u32 ipaddr) |
1301 | unsigned char hwaddr[6]) | ||
1302 | { | 1317 | { |
1303 | struct ifreq ifr; | 1318 | struct ifreq ifr; |
1304 | struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr; | 1319 | struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr; |
1305 | 1320 | ||
1306 | /* Don't read these incantations. Just cut & paste them like I did! */ | ||
1307 | memset(&ifr, 0, sizeof(ifr)); | 1321 | memset(&ifr, 0, sizeof(ifr)); |
1308 | strcpy(ifr.ifr_name, devname); | 1322 | strcpy(ifr.ifr_name, tapif); |
1323 | |||
1324 | /* Don't read these incantations. Just cut & paste them like I did! */ | ||
1309 | sin->sin_family = AF_INET; | 1325 | sin->sin_family = AF_INET; |
1310 | sin->sin_addr.s_addr = htonl(ipaddr); | 1326 | sin->sin_addr.s_addr = htonl(ipaddr); |
1311 | if (ioctl(fd, SIOCSIFADDR, &ifr) != 0) | 1327 | if (ioctl(fd, SIOCSIFADDR, &ifr) != 0) |
1312 | err(1, "Setting %s interface address", devname); | 1328 | err(1, "Setting %s interface address", tapif); |
1313 | ifr.ifr_flags = IFF_UP; | 1329 | ifr.ifr_flags = IFF_UP; |
1314 | if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) | 1330 | if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) |
1315 | err(1, "Bringing interface %s up", devname); | 1331 | err(1, "Bringing interface %s up", tapif); |
1332 | } | ||
1333 | |||
1334 | static void get_mac(int fd, const char *tapif, unsigned char hwaddr[6]) | ||
1335 | { | ||
1336 | struct ifreq ifr; | ||
1337 | |||
1338 | memset(&ifr, 0, sizeof(ifr)); | ||
1339 | strcpy(ifr.ifr_name, tapif); | ||
1316 | 1340 | ||
1317 | /* SIOC stands for Socket I/O Control. G means Get (vs S for Set | 1341 | /* SIOC stands for Socket I/O Control. G means Get (vs S for Set |
1318 | * above). IF means Interface, and HWADDR is hardware address. | 1342 | * above). IF means Interface, and HWADDR is hardware address. |
1319 | * Simple! */ | 1343 | * Simple! */ |
1320 | if (ioctl(fd, SIOCGIFHWADDR, &ifr) != 0) | 1344 | if (ioctl(fd, SIOCGIFHWADDR, &ifr) != 0) |
1321 | err(1, "getting hw address for %s", devname); | 1345 | err(1, "getting hw address for %s", tapif); |
1322 | memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, 6); | 1346 | memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, 6); |
1323 | } | 1347 | } |
1324 | 1348 | ||
1325 | /*L:195 Our network is a Host<->Guest network. This can either use bridging or | 1349 | static int get_tun_device(char tapif[IFNAMSIZ]) |
1326 | * routing, but the principle is the same: it uses the "tun" device to inject | ||
1327 | * packets into the Host as if they came in from a normal network card. We | ||
1328 | * just shunt packets between the Guest and the tun device. */ | ||
1329 | static void setup_tun_net(const char *arg) | ||
1330 | { | 1350 | { |
1331 | struct device *dev; | ||
1332 | struct ifreq ifr; | 1351 | struct ifreq ifr; |
1333 | int netfd, ipfd; | 1352 | int netfd; |
1334 | u32 ip; | 1353 | |
1335 | const char *br_name = NULL; | 1354 | /* Start with this zeroed. Messy but sure. */ |
1336 | struct virtio_net_config conf; | 1355 | memset(&ifr, 0, sizeof(ifr)); |
1337 | 1356 | ||
1338 | /* We open the /dev/net/tun device and tell it we want a tap device. A | 1357 | /* We open the /dev/net/tun device and tell it we want a tap device. A |
1339 | * tap device is like a tun device, only somehow different. To tell | 1358 | * tap device is like a tun device, only somehow different. To tell |
1340 | * the truth, I completely blundered my way through this code, but it | 1359 | * the truth, I completely blundered my way through this code, but it |
1341 | * works now! */ | 1360 | * works now! */ |
1342 | netfd = open_or_die("/dev/net/tun", O_RDWR); | 1361 | netfd = open_or_die("/dev/net/tun", O_RDWR); |
1343 | memset(&ifr, 0, sizeof(ifr)); | ||
1344 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; | 1362 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; |
1345 | strcpy(ifr.ifr_name, "tap%d"); | 1363 | strcpy(ifr.ifr_name, "tap%d"); |
1346 | if (ioctl(netfd, TUNSETIFF, &ifr) != 0) | 1364 | if (ioctl(netfd, TUNSETIFF, &ifr) != 0) |
1347 | err(1, "configuring /dev/net/tun"); | 1365 | err(1, "configuring /dev/net/tun"); |
1366 | |||
1348 | /* We don't need checksums calculated for packets coming in this | 1367 | /* We don't need checksums calculated for packets coming in this |
1349 | * device: trust us! */ | 1368 | * device: trust us! */ |
1350 | ioctl(netfd, TUNSETNOCSUM, 1); | 1369 | ioctl(netfd, TUNSETNOCSUM, 1); |
1351 | 1370 | ||
1371 | memcpy(tapif, ifr.ifr_name, IFNAMSIZ); | ||
1372 | return netfd; | ||
1373 | } | ||
1374 | |||
1375 | /*L:195 Our network is a Host<->Guest network. This can either use bridging or | ||
1376 | * routing, but the principle is the same: it uses the "tun" device to inject | ||
1377 | * packets into the Host as if they came in from a normal network card. We | ||
1378 | * just shunt packets between the Guest and the tun device. */ | ||
1379 | static void setup_tun_net(char *arg) | ||
1380 | { | ||
1381 | struct device *dev; | ||
1382 | int netfd, ipfd; | ||
1383 | u32 ip = INADDR_ANY; | ||
1384 | bool bridging = false; | ||
1385 | char tapif[IFNAMSIZ], *p; | ||
1386 | struct virtio_net_config conf; | ||
1387 | |||
1388 | netfd = get_tun_device(tapif); | ||
1389 | |||
1352 | /* First we create a new network device. */ | 1390 | /* First we create a new network device. */ |
1353 | dev = new_device("net", VIRTIO_ID_NET, netfd, handle_tun_input); | 1391 | dev = new_device("net", VIRTIO_ID_NET, netfd, handle_tun_input); |
1354 | 1392 | ||
@@ -1365,14 +1403,29 @@ static void setup_tun_net(const char *arg) | |||
1365 | 1403 | ||
1366 | /* If the command line was --tunnet=bridge:<name> do bridging. */ | 1404 | /* If the command line was --tunnet=bridge:<name> do bridging. */ |
1367 | if (!strncmp(BRIDGE_PFX, arg, strlen(BRIDGE_PFX))) { | 1405 | if (!strncmp(BRIDGE_PFX, arg, strlen(BRIDGE_PFX))) { |
1368 | ip = INADDR_ANY; | 1406 | arg += strlen(BRIDGE_PFX); |
1369 | br_name = arg + strlen(BRIDGE_PFX); | 1407 | bridging = true; |
1370 | add_to_bridge(ipfd, ifr.ifr_name, br_name); | 1408 | } |
1371 | } else /* It is an IP address to set up the device with */ | 1409 | |
1410 | /* A mac address may follow the bridge name or IP address */ | ||
1411 | p = strchr(arg, ':'); | ||
1412 | if (p) { | ||
1413 | str2mac(p+1, conf.mac); | ||
1414 | *p = '\0'; | ||
1415 | } else { | ||
1416 | p = arg + strlen(arg); | ||
1417 | /* None supplied; query the randomly assigned mac. */ | ||
1418 | get_mac(ipfd, tapif, conf.mac); | ||
1419 | } | ||
1420 | |||
1421 | /* arg is now either an IP address or a bridge name */ | ||
1422 | if (bridging) | ||
1423 | add_to_bridge(ipfd, tapif, arg); | ||
1424 | else | ||
1372 | ip = str2ip(arg); | 1425 | ip = str2ip(arg); |
1373 | 1426 | ||
1374 | /* Set up the tun device, and get the mac address for the interface. */ | 1427 | /* Set up the tun device. */ |
1375 | configure_device(ipfd, ifr.ifr_name, ip, conf.mac); | 1428 | configure_device(ipfd, tapif, ip); |
1376 | 1429 | ||
1377 | /* Tell Guest what MAC address to use. */ | 1430 | /* Tell Guest what MAC address to use. */ |
1378 | add_feature(dev, VIRTIO_NET_F_MAC); | 1431 | add_feature(dev, VIRTIO_NET_F_MAC); |
@@ -1382,11 +1435,14 @@ static void setup_tun_net(const char *arg) | |||
1382 | /* We don't need the socket any more; setup is done. */ | 1435 | /* We don't need the socket any more; setup is done. */ |
1383 | close(ipfd); | 1436 | close(ipfd); |
1384 | 1437 | ||
1385 | verbose("device %u: tun net %u.%u.%u.%u\n", | 1438 | devices.device_num++; |
1386 | devices.device_num++, | 1439 | |
1387 | (u8)(ip>>24),(u8)(ip>>16),(u8)(ip>>8),(u8)ip); | 1440 | if (bridging) |
1388 | if (br_name) | 1441 | verbose("device %u: tun %s attached to bridge: %s\n", |
1389 | verbose("attached to bridge: %s\n", br_name); | 1442 | devices.device_num, tapif, arg); |
1443 | else | ||
1444 | verbose("device %u: tun %s: %s\n", | ||
1445 | devices.device_num, tapif, arg); | ||
1390 | } | 1446 | } |
1391 | 1447 | ||
1392 | /* Our block (disk) device should be really simple: the Guest asks for a block | 1448 | /* Our block (disk) device should be really simple: the Guest asks for a block |
@@ -1698,7 +1754,7 @@ static struct option opts[] = { | |||
1698 | static void usage(void) | 1754 | static void usage(void) |
1699 | { | 1755 | { |
1700 | errx(1, "Usage: lguest [--verbose] " | 1756 | errx(1, "Usage: lguest [--verbose] " |
1701 | "[--tunnet=(<ipaddr>|bridge:<bridgename>)\n" | 1757 | "[--tunnet=(<ipaddr>:<macaddr>|bridge:<bridgename>:<macaddr>)\n" |
1702 | "|--block=<filename>|--initrd=<filename>]...\n" | 1758 | "|--block=<filename>|--initrd=<filename>]...\n" |
1703 | "<mem-in-mb> vmlinux [args...]"); | 1759 | "<mem-in-mb> vmlinux [args...]"); |
1704 | } | 1760 | } |