/*--- * Control hooks: * ipfw_ctl_h() is a wrapper for linux to FreeBSD sockopt call convention. * then call the ipfw handler in order to manage requests. * In turn this is called by the linux set/get handlers. */ static int ipfw_ctl_h(struct sockopt *s, int cmd, int dir, int len, void __user *user) { struct thread t; int ret = EINVAL; memset(s, 0, sizeof(*s)); s->sopt_name = cmd; s->sopt_dir = dir; s->sopt_valsize = len; s->sopt_val = user; /* sopt_td is not used but it is referenced */ memset(&t, 0, sizeof(t)); s->sopt_td = &t; if (ip_fw_ctl_ptr && cmd != IP_DUMMYNET3 && (cmd == IP_FW3 || cmd < IP_DUMMYNET_CONFIGURE)) ret = ip_fw_ctl_ptr(s); else if (ip_dn_ctl_ptr && (cmd == IP_DUMMYNET3 || cmd >= IP_DUMMYNET_CONFIGURE)) ret = ip_dn_ctl_ptr(s); return -ret; /* errors are < 0 on linux */ }
static void ip_fw_sockopt_dispatch(netmsg_t msg) { struct sockopt *sopt = msg->lmsg.u.ms_resultp; int error; KKASSERT(mycpuid == 0); if (IPFW_LOADED) error = ip_fw_ctl_ptr(sopt); else error = ENOPROTOOPT; lwkt_replymsg(&msg->lmsg, error); }
/* IRP_MJ_DEVICE_CONTROL for control device dispatcher */ NTSTATUS DispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp) { PIO_STACK_LOCATION irps = IoGetCurrentIrpStackLocation(irp); ULONG ioctl = irps->Parameters.DeviceIoControl.IoControlCode, len = irps->Parameters.DeviceIoControl.InputBufferLength, size = irps->Parameters.DeviceIoControl.OutputBufferLength; void *buf = irp->AssociatedIrp.SystemBuffer; NTSTATUS status; irp->IoStatus.Information = 0; // neccessary? switch (ioctl) { case IP_FW_SETSOCKOPT: case IP_FW_GETSOCKOPT: { struct sockopt *sopt; if (len < sizeof(struct sockopt)) { status = STATUS_INFO_LENGTH_MISMATCH; break; } sopt = (struct sockopt *)buf; // setup sopt->sopt_val if (sopt->sopt_valsize > 0) sopt->sopt_val = sopt->sopt_val_buf; else sopt->sopt_val = NULL; if (ip_fw_ctl_ptr != NULL) { status = ip_fw_ctl_ptr(sopt); if (status == STATUS_SUCCESS && ioctl == IP_FW_GETSOCKOPT) { irp->IoStatus.Information = sizeof(struct sockopt) + sopt->sopt_valsize; } } else status = STATUS_INVALID_PARAMETER; // ??? good status ??? break; } case IP_FW_SET_IFLIST: if (len < sizeof(struct ip_fw_iflist_entry)) { status = STATUS_INFO_LENGTH_MISMATCH; break; } status = iflist_setup((struct ip_fw_iflist_entry *)buf); break; case IP_FW_SYSCTL_IO: { struct sysctl *ctldata; int *n; if (len < sizeof(struct sysctl)) { status = STATUS_INFO_LENGTH_MISMATCH; break; } ctldata = (struct sysctl *)buf; switch (ctldata->sysctl_name) { case FW_ONE_PASS: n = _fw_one_pass; break; case FW_DEBUG: n = _fw_debug; break; case FW_VERBOSE: n = _fw_verbose; break; case FW_VERBOSE_LIMIT: n = _fw_verbose_limit; break; case DYN_BUCKETS: n = _fw_dyn_buckets; break; case CURR_DYN_BUCKETS: n = _fw_curr_dyn_buckets; ctldata->sopt_dir = SOPT_GET; break; case DYN_COUNT: n = _fw_dyn_count; ctldata->sopt_dir = SOPT_GET; break; case DYN_MAX: n = _fw_dyn_max; break; case STATIC_COUNT: n = _fw_static_count; ctldata->sopt_dir = SOPT_GET; break; case DYN_ACK_LIFETIME: n = _fw_dyn_ack_lifetime; break; case DYN_SYN_LIFETIME: n = _fw_dyn_syn_lifetime; break; case DYN_FIN_LIFETIME: n = _fw_dyn_fin_lifetime; break; case DYN_RST_LIFETIME: n = _fw_dyn_rst_lifetime; break; case DYN_UDP_LIFETIME: n = _fw_dyn_udp_lifetime; break; case DYN_SHORT_LIFETIME: n = _fw_dyn_short_lifetime; break; #ifndef IPFW2 case DYN_GRACE_TIME: n = _fw_dyn_grace_time; ctldata->sopt_dir = SOPT_GET; #else case DYN_KEEPALIVE: n = _fw_dyn_keepalive; #endif break; default: break; } if (ctldata->sopt_dir == SOPT_SET) { *n = ctldata->sysctl_val; } ctldata->sysctl_val = *n; irp->IoStatus.Information = sizeof(struct sysctl); status = STATUS_SUCCESS; break; } default: status = STATUS_NOT_SUPPORTED; } irp->IoStatus.Status = status; IoCompleteRequest(irp, IO_NO_INCREMENT); return status; }