From owner-freebsd-hackers Thu Apr 23 05:56:01 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id FAA25503 for freebsd-hackers-outgoing; Thu, 23 Apr 1998 05:56:01 -0700 (PDT) (envelope-from owner-freebsd-hackers@FreeBSD.ORG) Received: from ns1.yes.no (ns1.yes.no [195.119.24.10]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id FAA25484 for ; Thu, 23 Apr 1998 05:55:57 -0700 (PDT) (envelope-from eivind@bitbox.follo.net) Received: from bitbox.follo.net (bitbox.follo.net [194.198.43.36]) by ns1.yes.no (8.8.7/8.8.7) with ESMTP id MAA28841 for ; Thu, 23 Apr 1998 12:55:54 GMT Received: (from eivind@localhost) by bitbox.follo.net (8.8.8/8.8.6) id OAA03070; Thu, 23 Apr 1998 14:55:53 +0200 (MET DST) Message-ID: <19980423145553.50690@follo.net> Date: Thu, 23 Apr 1998 14:55:53 +0200 From: Eivind Eklund To: hackers@FreeBSD.ORG Subject: Re: changing ipfw interface (was Re: cvs commit: src/sys/netinet ip_fw.c) References: <19980423015125.15103@follo.net> <9804231048.AA01717@avalon.reed.wattle.id.au.> <19980423135332.35381@follo.net> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Mailer: Mutt 0.89.1i In-Reply-To: <9804231048.AA01717@avalon.reed.wattle.id.au.>; from darrenr@reed.wattle.id.au on Thu, Apr 23, 1998 at 08:44:05PM +1000 Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG This was supposed to go here, not in private to Darren :-( (I'll try to get his permission to forward his reply). On Thu, Apr 23, 1998 at 08:44:05PM +1000, darrenr@reed.wattle.id.au wrote: > In some email I received from Eivind Eklund, sie wrote: > > > > On Thu, Apr 23, 1998 at 01:50:05AM +1000, darrenr@reed.wattle.id.au wrote: > > > In some email I received from Eivind Eklund, sie wrote: > > > > > > > > That's what I'm saying - it blow the userland interface. It means > > > > that anything using IPFW has to track the kernel version exactly. > > > > > > There are numerous programs like this already - ps, netstat, top, etc. > > > > > > I'd say "deal with it". > > > > ps et.al. aren't that critical. Sure, it suck that they are that > > way, but if ps is broken, _you can still get to the machine_. This is > > not the case with IPFW. Having a structure-dependent interface for > > the firewall is IMO not acceptable. > > Then maybe ipfw is `being handled wrongly'. You have code which lives in > the kernel that must interface with the userland *tightly*. That entire > bundle must stay consistant with respect to versions. It's not so much > dependant on the kernel version, but rather you're changing the "ipfw" > version when you change the kernel or user code. I don't care what I'm changing. I don't have a problem keeping my own machines working (though I must admit I feel slightly scared when I do remote updates that change IPFW). My problem is that I see _users_ being screwed by this each time we change IPFW. > For what it's worth, using ipfw as an LKM (which isn't compiled out of > /sys) maybe what you're really thinking of here although then your kernel > security drops. Actually, I'm not sure what you're proposing makes any > difference unless you're planning on using BPF to write ipfw rules, as > the interface becomes `programmable' (along with the bloat required in > the kernel to support it unless that's not a factor in your requirements). I've included (below) the original mail I sent to hackers on the subject. This interface allow anything that would 'just have required a re-compile of the old sources' to work. Anything else means we also have an unstable programmatic interface; that's _bad_, unless we're going to say that only /sbin/ipfw is going to be allowed to use that interface. Eivind. -------------------- Message-ID: <19980131071101.11786@follo.net> Date: Sat, 31 Jan 1998 07:11:01 +0100 From: Eivind Eklund To: hackers@FreeBSD.ORG Subject: On a new IPFW interface, w/potentially wider applications Lines: 196 Does the below (inspired by tags on the Amiga) sound like a good idea for IPFW? Does it sound like it is such a good idea that it should be extended to a generic method of manipulating kernel objects instead of doing it only for IPFW? (Cost: At least one syscall number, up to four if we want separate syscalls for add/delete/commit/cancel, as well as making it approx twice as much work to implement as a special case for IPFW). And speaking of kernel interfaces: I've been thinking of a way of implementing capabilites (in the security sense) which would share a lot of properties with this interface, and might be cheap to implement along with it (I'd have to look more closely at the design issues to be certain). Do anybody but me feel that this (capabilites) would be a good direction to go for FreeBSD, or do people think we'll become 'too weird' that way? [Originally in a mail to Alex Nash] Speaking of the IPFW interface: I am quite tired of seeing necessary changes to that break other software. What do you say about an interface like the below? If that's OK, I'll look into implementing it or getting my mentoree to do it (unless you have enough time and want to do it yourself to get it done quickly :-) The basic idea behind the below is the make the interface create rules by itself with default values first, and then change the created rule by a set of setsockopt() calls until its parameters is correct. The new rule is then added to the list by a commit operation. Implementation detail: The interface should limit the number of non-committed rules to a fixed number, to stop kernel resource starvation by a userland process. Old non-committed rules should probably be thrown away in preference to new ones being denied; that will more easily protect against programming errors. I think a new new userland library for easy access to this would be a good idea; see bottom for details on how I envision this. ------------------------------------------------------------------ New socket options: IP_FW_START_ADD: struct { long version; /* Interface version, below is version 0 */ unsigned long list; /* Which rule list to work with (0 is the only presently correct list number) */ int number; /* "Line number"/rule number for IPFW */ unsigned long coookie; /* Filled in by the kernel; used as a capability (in the security sense) to identify this add operation for later manipulation. */ } This socket option starts a new add request; the add request will be filled with data and committed to the firewall lists later. List is allowed to be able to have more than one firewall list later, to allow filtering the way Cisco implements it. (If the structure is not copied to the kernel for a getsockopt() operation, we'll just have to make do with just returning a cookie. The above implementation would be preferable, as we won't have to specify as many parameters for to IP_FW_SET, and can upgrade the interface at will). IP_FW_SET: struct { unsigned long cookie; /* Previously returned from IP_FW_START_ADD. This identify which non-completed rule to manipulate. */ unsigned long field; /* Which field of the rule to manipulate */ unsigned char data[92]; /* The data for this field. 92 will allow it to fit in a 108 byte socket option together with a 64-bit cookie and 'field' ;-) */ } Manipulate the field of an as-of-yet uncommitted rule. IP_FW_COMMIT: struct { unsigned long cookie; /* The capability of the rule to commit */ } Commit a new rule into the kernel. IP_FW_CANCEL: struct { unsigned long cookie; /* The capability of the rule to cancel */ } Drop a rule that has been built in the kernel. IP_FW_START_GET: struct { long version; /* Version of interface to use (presently 0) */ unsigned long list; /* Which list of rules to get (presently 0) */ unsigned long cookie; /* Capability; filled in by the kernel. */ } Get a capability for getting a list of firewall rules from the kernel. IP_FW_GET_VALUE: struct ip_fw_get_value_struct { unsigned long cookie; /* Capability for getting data */ unsigned long field; /* Which field to get */ unsigned char data[92]; /* Data gotten from the kernel */ } Get the data for a field from the kernel. If we can't pass this structure to the kernel, we're in mucho, mucho trouble, and probably will need to connect the state of reading a list to a particular socket, which would be a pity. The size of the data read from the kernel is found by subtracting offsetof(struct ip_fw_get_value_struct,data) from the amount of data the kernel says it has written. IP_FW_GET_NEXT: struct { unsigned long cookie; /* Capability for reading operation in the kernel we're presently manipulating. */ } Proceed to next rule along a rule-list we're reading. IP_FW_GET_DONE: struct { unsigned long cookie; /* Capability for reading operation in the kernel we're presently manipulating. */ } Finish with the capability for a particular read operation. ------------------------------------------- Now, to make the userland side of this easy, I would like an access library: int ipfw_addrule( unsigned long list_number, unsigned long rule_number, ...); where ... is filled with option/value pairs, like in (long)IPFW_SRCADDR, &inaddr, (long)IPFW_PORT, 6667, (long)0 /* Termination */ For deletion, int ipfw_delrule( unsigned long list_number, unsigned long rule_number ); For getting lists: { unsigned long cookie; struct ip_fw rule; cookie = ipfw_getlist_start(0); /* List number */ if (!cookie) return; while (ipfw_getlist_entry(cookie, IPFW_SRCADDR, &rule.fw_src, IPFW_DSTADDR, &rule.fw_dst, IPFW_SRCMASK, &rule.fw_smsk, IPFW_DSTMASK, &rule.fw_dmsk, (long)0)) { ... do stuff ... } ipfw_getlist_done(cookie); } The data don't have to go into the old ip_fw struct, of course - that's just as an example. Well, what do you think? It covers our present needs, and as far as I can see our future needs - if we need single fields of more than 92 bytes we can always set them as several operations or change the interface by changing the version. It allow us to add entries to the data structures without killing old apps. It should be fairly easy to implement, and fairly easy for programmers to use, especially if we add the library. Eivind. To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message