aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/lguest/lguest.c
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/lguest/lguest.c')
-rw-r--r--Documentation/lguest/lguest.c122
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
1266static u32 str2ip(const char *ipaddr) 1266static 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
1275static 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. */
1300static void configure_device(int fd, const char *devname, u32 ipaddr, 1316static 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
1334static 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 1349static 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. */
1329static 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. */
1379static 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[] = {
1698static void usage(void) 1754static 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}