+ case SIOCGIFFLAGS:
+ ifr.ifr_flags = tun->if_flags;
+ if (copy_to_user( argp, &ifr, sizeof ifr))
+ return -EFAULT;
+ return 0;
+
+ case SIOCSIFFLAGS:
+ /** Set the character device's interface flags. Currently only
+ * IFF_PROMISC and IFF_ALLMULTI are used. */
+ tun->if_flags = ifr.ifr_flags;
+ DBG(KERN_INFO "%s: interface flags 0x%lx\n",
+ tun->dev->name, tun->if_flags);
+ return 0;
+
+ case SIOCGIFHWADDR:
+ memcpy(ifr.ifr_hwaddr.sa_data, tun->dev_addr,
+ min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr));
+ if (copy_to_user( argp, &ifr, sizeof ifr))
+ return -EFAULT;
+ return 0;
+
+ case SIOCSIFHWADDR:
+ /** Set the character device's hardware address. This is used when
+ * filtering packets being sent from the network device to the character
+ * device. */
+ memcpy(tun->dev_addr, ifr.ifr_hwaddr.sa_data,
+ min(sizeof ifr.ifr_hwaddr.sa_data, sizeof tun->dev_addr));
+ DBG(KERN_DEBUG "%s: set hardware address: %x:%x:%x:%x:%x:%x\n",
+ tun->dev->name,
+ tun->dev_addr[0], tun->dev_addr[1], tun->dev_addr[2],
+ tun->dev_addr[3], tun->dev_addr[4], tun->dev_addr[5]);
+ return 0;
+
+ case SIOCADDMULTI:
+ /** Add the specified group to the character device's multicast filter
+ * list. */
+ add_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
+ DBG(KERN_DEBUG "%s: add multi: %x:%x:%x:%x:%x:%x\n",
+ tun->dev->name,
+ (u8)ifr.ifr_hwaddr.sa_data[0], (u8)ifr.ifr_hwaddr.sa_data[1],
+ (u8)ifr.ifr_hwaddr.sa_data[2], (u8)ifr.ifr_hwaddr.sa_data[3],
+ (u8)ifr.ifr_hwaddr.sa_data[4], (u8)ifr.ifr_hwaddr.sa_data[5]);
+ return 0;
+
+ case SIOCDELMULTI:
+ /** Remove the specified group from the character device's multicast
+ * filter list. */
+ del_multi(tun->chr_filter, ifr.ifr_hwaddr.sa_data);
+ DBG(KERN_DEBUG "%s: del multi: %x:%x:%x:%x:%x:%x\n",
+ tun->dev->name,
+ (u8)ifr.ifr_hwaddr.sa_data[0], (u8)ifr.ifr_hwaddr.sa_data[1],
+ (u8)ifr.ifr_hwaddr.sa_data[2], (u8)ifr.ifr_hwaddr.sa_data[3],
+ (u8)ifr.ifr_hwaddr.sa_data[4], (u8)ifr.ifr_hwaddr.sa_data[5]);
+ return 0;
+