Phase 1 Code Review Feedback

Original webrev

General

Reviewer/ID Comment Disposition Status
meem-001 A number of functions are named without appropriate prefixes (e.g. nwam_) in ways that encroach upon actively evolved public namespaces. For instance, door_switch() and and dlpi_notify(). ACCEPT done
meem-002 A number of functions use chumminess with lint to make arguments appear to be used (e.g., `foo = foo'). This is not a robust or clear way to handle unused arguments; please use ARGSUSED or the NOTE() facility to mark unused arguments. ACCEPT done
meem-003 A number of places seem to check for pthread_mutex_lock() failure. This is needless: there are no cases short of programmer error that will lead to pthread_mutex_lock() failing (for a normal pthread lock). ACCEPT done
paul-01 s/IPSec/IPsec/ mph ACCEPT done
sowmini-02 why is netcfgd under $SRC/cmd/cmd-inet/lib/netcfgd? Seems like this is parallel to dlmgmtd for layer 3, so to be symmetric with dlmgtd, shouldn't it be under $SRC/cmd/netcfgd/*? at the very least, it would make sense to have $SRC/cmd/cmd-inet/nwam/netcfgd and $SRC/cmd/cmd-inet/nwam/nwamd ($SRC/cmd/cmd-inet/lib is misleading, since I don't think these apps get installed in /lib), but I think the cleaner solution is
    $SRC/cmd/nwam/netcfgd
    $SRC/cmd/nwam/nwamd
    $SRC/cmd/nwam/common /* for common themes like daemonize() */
DISCUSS (thread) done

Packaging/RBAC

Reviewer/ID Comment Disposition Status
DJM-01 user_attr: why aren't dladm,netadm,netcfg marked as roles ? Users shouldn't login to them directly right (yes I know they have locked accounts) DISCUSS (thread) done
DJM-02 SUNWcrnet/postinstall: how is this going to be done in an IPS world ? REJECT (thread) done
DJM-03 i.passwd: the change for dladm's group doesn't look like it will work for upgrade, see how I did the home dir change for the gdm user. ACCEPT done
paul-05/06 exec_attr.txt: So, you have nwamadm and nwamcfg as part of the "Network Management" profile. But "Network IPsec Management" is part of "Network Security" and "IP Filter Management" appears to be in its own bucket (which is a pre-existing bug IMO, it should be in Network Security). It is not part of "Network Management", possibly on purpose. Anyway, nwamcfg and nwamadm implicitly give you the ability to manage IPfilter and IPsec policies if you have the solaris.network.autoconf.write authorization since you can define a property to override security policy. In fact, you must supply a property or policy gets blanked out IIRC. This is leaking the separation of privileges. What is the intention here as far as the privilege and authorization model? I'm not sure what the right balance is for your project and the previous requirements that caused this separation in the first place. DISCUSS (thread) done
paul-07 user_attr.txt: Does netadm need the IPfilter service listed? DISCUSS (thread) done
tony-14 Can changes in SUNWcnetr/postinstall be avoided? That is the mechanism should not rely on postinstall script since that wouldn't work with OpenSolaris. DUP (DJM-02) done
sowmini-01 what is the difference between the netadm and netcfg uids? The Brussels II project is considering setting up /sbin/ipadm as owned by some dladm-like uid, and we had assumed this would be netadm. Should it be netcfg? DISCUSS (thread) done

libinetcfg

Reviewer/ID Comment Disposition Status
seb-01 inetcfg.c'General: I find it strange that an icfg_handle_t can either represent an IP interface or an IP address (i.e.: "logical interface"). It gives many of the new functions introduced have dual-functionality. For example, icfg_unplumb() is actually the same as icfg_remove_ipaddr() if the handle happens to be a "logical" interface. I would think that the model would be simpler if a handle were to strictly refer to an IP interface. You could have a different handle type for IP addresses if necessary.    
seb-02 inetcfg.c'General: Why not simplify ifconfig.c by having it use the new functions?    
seb-03 inetcfg.c'84: The user probably won't know what "Invalid DLPI link" means. Most don't know what DLPI is, as it's an API, and not something that exists at the administrative level. It would make more sense to me to have the DLPI_ENOLINK libdlpi error map to something that prints "link does not exist" or something similarly tangible.    
seb-04 inetcfg.c'86-90: These error strings are also quite implementation-specific, but since there's absolutely nothing that the admin can do about them, then it's probably not worth making them more friendly (unless you can think of something better).    
seb-05 inetcfg.c'92: I find it simpler without a count, and instead have a NULL-terminated array (e.g.: a last entry with a NULL error_desc).    
seb-06 inetcfg.c'116: You've just lost the actual error here. When DL_SYSERR is returned, errno indicates the actual system error code (see dlpi_strerror(3DLPI)). It would be good to indicate that error instead of a cryptic "DLPI error". For example, if it was ENOMEM, then you at least have a chance to print something meaningful given that you already have ICFG_NO_MEMORY.    
seb-07 inetcfg.c'2068: The addrlen argument is effectively not used; it should be removed.    
seb-08 inetcfg.c'2076,2079: You should verify sa_family == icfg_if_protocol()here.    
seb-09 inetcfg.c'2101 and almost every other place where errno gets set: ICFG_FAILURE ends up printing "Generic failure", which is not useful given that an actual specific error occured that was stored in errno. A function that translates errno's to ICFG_* errors would make this facility better. You'll need something like that anyway to address my previous concern regarding the mishandling of DL_SYSERR.    
seb-10 inetcfg.c'2171: This restriction seems unwarranted. Moreover, the condition it checks for can change immediately after the check, so even if it were intentional, it's not effective.    
seb-11 inetcfg.c'2193,2214,2270,2487: These duplicate code in ifconfig.c. ifconfig.c should be made to call these functions instead of maintaining two versions of the same code.    
seb-12 inetcfg.c'2270: There is no longer a plumb_one_device() in ifconfig.c, it's now ifplumb().    
seb-13 inetcfg.c'2282: Remove spurious blank line. The indentation below also doesn't match above.    
seb-14 inetcfg.c'2290: An interface with the given name could be plumbed immediately after the check, so it doesn't add much value. Doesn't SIOCSLIFNAME already fail with an appropriate error code if the interface already exists anyway?    
seb-15 inetcfg.c'2347: What is "name string" referring to here?    
seb-16 inetcfg.c'2358,2535: Use strlcpy(). strncpy() can lead to subtle bugs since it doesn't guarantee that the result is NULL-terminated.    
seb-17 inetcfg.c'2499: Remove spurious blank line.    
seb-18 inetcfg.c'2501: Need blank line between variable declarations and code.    
sowmini-10 libinetcfg/Makefile: not sure I understand why this is necessary? According to $SRC/lib/README.Makefiles, after you define HDRS and HDRDIR, you one need check: $(CHECKHDRS) Could you explain why this is needed?    
sowmini-11 inetcfg.c'icfg_get_linkinfo is a dead function - can be removed    
sowmini-12 inetcfg.c: Not your introduction, but icfg_get_flags(), icfg_get_metric(), icfg_get_mtu(), icfg_get_index() should bzero the lifr as a first step. Also, these are exported functions that could be called with a NULL second argument, so they should verify that the flags/metric/etc. is not null before trying to set them.    
sowmini-13 inetcfg.c'1854: list == NULL, can happen if there are no links available, so I think this should only return ICFG_NO_MEMORY if lwp->lw_err = ENOMEM. also it may be that we ran out of memory half way through the walk, so we may still need to free memory. i.e., we shoudl goto done, and do
   for (i = 0; i < lwp->lw_num; i++) {
                free(..);
   }
   
sowmini-14 inetcfg.c'1863: why only AF_INET?    
sowmini-15 inetcfg.c'icfg_plumb(): does this need to verify zone_check_datalink()? (ifconfig does this in inetplumb before calling ifplumb)    
sowmini-16 inetcfg.c'2333-2334: comments are incorrect - after the fix for CR6243060, the kernel only allows modifications to IFF_IPv4, IFF_IPV6, IFF_BROADCAST, IFF_XRESOLV. Thus you could skip lines 2339-2345, and instead start with lifr_flags of 0, before doing lines 2348-2354.    
sowmini-17 inetcfg.c'2368-2374: call icfg_get_flags instead of inlining this code.    
sowmini-18 inetcfg.c: is it necessary to expose errors like ICFG_NO_UNPLUMB_ARP/ICFG_NO_PLUMB_IP etc? How is the caller supposed to make sense of these errors? i.e., collapse lines 86-90 to two errors, ICFG_IF_CREATE_ERR and ICFG_IF_DESTROY_ERR (or some such pair of error codes)    
sowmini-19 inetcfg.c: Question: it looks like we need separate icfg_handle structures for IPv4 and IPv6 interfaces with nwamd_plumb_unplumb_interface being passed an af to plumb. How is the af determined (seems like the nwamd_ncu_state_machine figures this out. Also, I would have expected the code to do something like
    icfg_open()
    plumb interface
    add addresses
    ... other stuff with the interface..

and maybe only do the icfg_close when the interface is unplumbed (but even that would result in needless creation of the ifh_sock), but I see an icfg_open/icfg_close pair for each operation like icfg_plumb, icfg_add_ipaddr etc. which would give rise to 6745288-like problems? Ideally we should have a single handle for ipv4 and ipv6 (with ifh_sock4, ifh_sock6), and then use the address itself to figure out which af was targetted (as needed). If that's not possible (because there are a lot of functions like icfg_set_mtu/icfg_set_metric which, though they are dead code with questionable semantics, are not getting cleaned up by this proposal) we should be restricting nwam usage of icfg_open to retain handle(s) for as long as possible, instead of doing an open/close per operation.

   
sowmini-20 inetcfg.c'icfg_unplumb: if called with an ipmp interface, do we want to bail? (you would notice IFF_IPMP at line 2541)    
sowmini-21 inetcfg.c: If the PUNLINK of the arp stream fails at
  2570                          } else {
  2571                                  ret = ICFG_NO_UNPLUMB_ARP;
  2572                                  goto done;
  2573                          }

the code bails out and doesn't try to unplumb the IP stream, whereas onnv seems to- was this difference intentional?

   
sowmini-22 libinetcfg/common/mapfile-vers: see coments for inetcfg.h - looks like only icfg_plumb, icfg_remove_ipaddr amd icfg_unplumb need to be added.    
sowmini-23 inetcfg.h: icfg_is_logical is not exported, so it can be made static to inetcfg.c. Similarly icfg_is_loopback, icfg_if_protocol.    
sowmini-24 llib-linetcfg: no changes to this file?    

nwamd (Michael Hunter)

Reviewer/ID Comment Status
meem-094 nwamd/dlpi_events.c'Throughout: libdlpi does not use `errno' for errors. All of the dlpi-related log messages in this file are busted. done
meem-095 nwamd/dlpi_events.c'34: Unclear what net/route.h has to do with this file. done
meem-096 nwamd/dlpi_events.c'65: This `if' clause is needless: nwamd has requested to only receive events of these two types. done
meem-097 nwamd/dlpi_events.c'67: Use of 'IFF_UP' to have some relationship to the link state seems wrong. Seems like it would be simpler to change link_state.link_state to link_state.link_up and just have it be a boolean. BUG
meem-098 nwamd/dlpi_events.c'71: Shouldn't this message explain the administrative impact? done
meem-099 nwamd/dlpi_events.c'88-102: Unclear why this function is allocating a buffer to receive into since it does nothing with this buffer – and even more unclear why this buffer is sized to DLPI_PHYSADDR_MAX. Seems like this whole function should just be:
           static void *
           nwamd_dlpi_thread(void *arg)
           {
                int rc;
                dlpi_handle_t *dh = arg;

                for (;;) {
                        rc = dlpi_recv(*dh, NULL, NULL, NULL, NULL, -1, NULL);
                        if (rc != DLPI_SUCCESS) {
                                nlog(LOG_ERR, "nwam_dlpi_thread: dlpi_recv "
                                    "failed: %s", dlpi_strerror(rc));
                                break;
                        }
                }
                return (NULL);
           }
done
meem-100 nwamd/dlpi_events.c'94: Bogus cast. done
meem-101 nwamd/dlpi_events.c'99: Unclear where the magic notion of three failures comes from; one would think any unexpected failure would be worth stopping for. done
meem-102 nwamd/dlpi_events.c'100: presumably *dh was meant? bug
meem-103 nwamd/dlpi_events.c'105: This function would be much easier to read if a local variable was declared for ncu->ncu_node.u_link. done
meem-104 nwamd/dlpi_events.c'123: Can this happen? If so, what prevents a situation where two thread simultaneously pass this check and race to both call pthread_create()? BUG
meem-105 nwamd/dlpi_events.c'135, 182: Comments only tell me what is clear already from the code. done
meem-106 nwamd/dlpi_events.c'136-146: dlpi_bind() is no longer needed to use dlpi_enabnotify(). done
meem-107 nwamd/dlpi_events.c'150: Sure seems like `strdup(name)' ends up getting leaked here. Shouldn't this be NULL? done
meem-108 nwamd/dlpi_events.c'160: Presumably the intent is to record the error value returned from pthread_create() in the nlog() message? done
seb-019 How about moving nwamd out of usr/src/cmd/cmd-inet/... and up to usr/src/cmd? Renee
seb-020 README: This file is a very nice touch. More subsystems need this kind of documentation for developers. done
seb-021 README: Is there room for an nwam dtrace provider that can help track the various states of the objects maintained by nwamd to help with debugging? The strategy for debugging problems could include "give me the output of this dtrace script" instead of (or maybe in addition to) the current "set the debug SMF property, enable debugging in syslog, and give me the output of the syslog file". EXPLAIN
seb-022 README'124: It would help to expand the NCP, NCU, and ENM acronyms at least once in the README. done
seb-023 Makefile: For a daemon as central and critical to the system's operation as nwamd, it should be compiled with CTF data so that it can be debugged with dtrace and mdb. See the in.mpathd Makefile for an example of how to do this. done
seb-024 objects.h'45-52: There are over 90 other declarations of "object_name" in ON. Please use nwam-specific prefixes in nwam data structures to help with navigation of the code. done
seb-025 objects.h'47,48: Use of "void *" for object data defeats compiler type-checking and is not generally good practice. At a guess, shouldn't object handle be of type "struct nwam_handle *"? object_data could be pointer to a union or just a union (does object_data need to be allocated separately?). done
seb-026 ncu.h'70-99: Members need some identifying prefix. E.g., I have no hope of getting at "flags" or "dhp" from cscope. Please go through all data structures and rectify this where necessary. done
seb-027 main.c'71: There's not much point in making this a global variable in main.c since it's only used in one place in conditions.c, but I'm wondering why it's not initialized by an SMF property like other timer-related intervals. done
seb-028 main.c'71: Related to wlan_scan_interval, if the user manually selected a specific WLAN link, I would think that the daemon doesn't scan every 120 seconds. For some WiFi drivers, initiating a scan can have really strange side-effects, including blocking data for extended periods of time and experiencing link flaps. It would be nice to have a mode where the daemon doesn't continually scan for no reason. RFE
seb-029 main.c'82: And that nice README that comes with the source... done
seb-030 main.c'143: This isn't used outside of main.c and should be static. In accordance to csctyle guidelines, it also needs to go at the top of the file with other globals. done
seb-031 main.c'170: refresh() calls nwamd_init_ncus() along with other nwamd_init_<stuff>() functions. Do these init routines handle cleaning up the existing objects before initializing? If they clean up, then why is nwamd_fini_ncus() called on line 169? If they don't, then why don't we need to call nwamd_fini_<stuff>() before the refresh() call on 173? BUG
seb-032 main.c'172: I'm wondering why SIGHUP is any different from SIGTHAW. Shouldn't both signals essentially result in re-creating the nwamd universe from scratch as if it were starting anew? BUG/EXPLAIN
seb-033 main.c'242: There's no need for any of these local variables; you can pass the addresses of the global variables into nwamd_lookup_boolean_property(). BUG
seb-034 main.c'288: Consider renaming to nwamd_refresh() for easier cscope browsing. done
seb-035 main.c'347: I may be misunderstanding how this works, but what is the point of enqueuing an event here if the daemon is immediately going to exit() (the event might still be in the queue when that happens). Did I miss something? EXPLAIN
seb-036 main.c'414: I don't see how zonename is used anywhere. It should probably be removed (along with nwamd_lookup_zonename()). done
seb-037 main.c'424: Using dladm_status2str() to include additional information would be good. BUG
seb-038 main.c'444: What's this SOFT_RESET_FILE about? It doesn't look like it's used anywhere. EXPLAIN
seb-039 main.c'480: door_initialize() should return an error code that can be converted to a printable string passed to pfail(). Another approach would be to have door_initialize() pfail() upon failure and have it return void (which is what you do for other init routines). BUG
seb-040 main.c'481: What kind of error handling did you have in mind? Killing the daemon seems perfectly reasonable since this looks like a fatal error condition. EXPLAIN/BUG
seb-041 door_if.c'73-776: The length of this function and its deep indentation makes it hard to read and thus review. I'd suggest processing of each request type in separate functions to help readability and reduce indentation. RFE
seb-042 door_if.c'85-88: what is this existentialist code about? If it's for lint, please remove this and use ARGSUSED instead. BUG
seb-043 door_if.c'91: Copying the data would aleviate the need for LINTED tags. BUG
seb-044 door_if.c'116,etc.: There's a lot of duplicate auth-checking code throughout this file. It might be simpler to have a simple table of door commands and associated required authorizations that could be checked prior to the switch. RFE
seb-045 door_if.c'133: Why is there no auth check for this command? BUG/EXPLAIN
seb-046 door_if.c'136: A WLAN scan request should require an authorization and/or elevated privileges, as it negatively impacts performance during the scan (severely for some drivers). The dladm scan-wifi subcommand requires sys_dl_config. RFE/BUG
seb-047 door_if.c'161: I believe that the res data is leaked here. door_return() never returns... Use alloca() instead. done
seb-048 door_if.c'177: What does this do? If it connects to a WLAN, then there should be some authorization check associated with this command. RFE/BUG
seb-049 door_if.c'214,308: The code for enable and disable is almost identical. I'm sure this could be refactored. RFE
seb-050 door_if.c'229: Why don't we record success for other audit checks in this function? Is that a bug? BUG
seb-051 door_if.c'251,281,345,375: This locking scheme to check for object state is at odds with the event queue scheme, and will likely lead to unexpected results. Locking the object to check its state cannot work reliably since there could be an event pending ahead of this request that changes the state immediately after you drop the lock and before you enqueue the event associated with this request. The NWAM_ENTITY_INVALID_STATE error returned by these door calls is thus meaningless. The state of the object cannot be reliably be checked until previous enqueued events are processed, and this event is dequeued. Given the event queue design, the best you probably can do is enqueue the request without checking the state, since you have no idea what the pending state of the object is (unless you can think of something better). EXPLAIN
seb-052 door_if.c'255,285,349: The same synchronization problem exists for these objects. There could be enqueued events that change the current active object, and thus checking the name of the current active object without consideration for pending events will lead to unexpected results. EXPLAIN/BUG
seb-053 door_if.c'255,285,349: The "active_loc" string could be in the middle of being modified by nwamd_loc_activate(). Same comment for the other strings being compared. BUG
seb-054 door_if.c'255,285,349: What verifies the input? The string could be non-NULL-terminated garbage. There should be a strlcpy() somewhere that verifies for overrun. BUG
seb-055 door_if.c'480-519: I don't see how this code can reliably work. Each action gets enqueued, so you have no way to verify if it succeeded. As such, the strategy of a rename operation being two separate operations (destroy and refresh) can result in an object being destroyed or a refresh action being processed when the destroy actually failed. EXPLAIN/BUG
seb-056 door_if.c'573,588: This doesn't take into account pending requests in the event queue. Those could very well be the requests from the door client to disable the very objects that it wants to destroy... EXPLAIN/BUG
seb-057 door_if.c'643: Why do you need a special case for the active location? Can it not be looked up using nwamd_object_find()? If yes, then you don't need that block of code. If not, then there's a race condition since "active_loc" could be in the process of being written to by nwamd_loc_activate(), which will result in an erroneous NWAM_ENTITY_NOT_FOUND. BUG
seb-058 door_if.c'791: I'd suggest using DOOR_REFUSE_DESC as well if you don't intent to handle file-descriptor passing through this door. BUG
seb-059 door_if.c'797: cstyle: need blank line between variables and code. BUG
seb-060 door_if.c'827: You could make doorfd a global I suppose, and you could close it BUG
seb-061 coditions.c'49: Yes, conditions are usually conditional. BUG
seb-062 coditions.c'94: Need block comment explaining what this does. BUG
seb-063 coditions.c'111,113: I don't grok this code. What does NWAM_CONDITION_IS mean? This looks needlessly complicated. Why not just have a function that returns the state of the object and have the caller do what it wants with it... EXPLAIN/BUG
seb-064 coditions.c'565: "ret" is not descriptive enough given that it has deeper semantics. It represents the state of some object. BUG
seb-065 coditions.c'608: There should be a comment somewhere (perhaps at the top of this file) explaining what CONDITIONAL_ANY and CONDITIONAL_ALL mean. I'm really not sure what this is designed to do. BUG
seb-066 dlpi_events.c'58,87: Please give these more distinguished names. BUG
seb-067 dlpi_events.c'67: IFF_UP is an IP interface flag; it is not a link state. There is a link_state_t defined in <sys/mac.h> that you can use for this purpose. BUG
seb-068 dlpi_events.c'82-84: This needs further clarification in the comment. You're only interested in notifications, and notifications are only processed in a pending dlpi_recv(). As such, you need to continuously call dlpi_recv() even if you're not interested in any other DLPI messages. BUG
seb-069 dlpi_events.c'99: This needs some comments, as I'm not clear on what it implies. Does the DLPI notification thread for this link simply vanish if it gets three consecutive read errors? What happens to the rest of the handling for that link if that happens? BUG
seb-070 dlpi_events.c'103: Need block comment. BUG
seb-071 dlpi_events.c'116: This can't possibly happen, right? Shouldn't this be an assert()? BUG
seb-072 dlpi_events.c'131,144,156,167: It would be simpler and less error-prone to declare a name string of appropriate size on the stack, and have nwam_ncu_typed_name_to_name() (that's quite a mouthful) use it instead of having it dynamically allocate memory. BUG
seb-073 dlpi_events.c'130,142,154: The use of errno in these locations is a bug: dlpi_open() only sets errno if the error is DL_SYSERR. You should use dlpi_strerror() on the returned libdlpi error code to print something meaningful, it handles this cleanly. done
seb-074 enm.c'50: Please elaborate a little bit here and explain what an "external network modifier" abstraction is. BUG
seb-075 enm.c'123: You're leaking object_name here. done
seb-076 enm.c'134: You make this lengthy check numerous times in this function. I'd suggest defining a boolean_t called goingonline (or something like that) as a local variable and setting it to (object->object_state == NWAM_STATE_OFFLINE_TO_ONLINE). RFE
seb-077 enm.c'165: The only possible first argument for nwamd_start_child() is CTRUN (nwamd_start_child() is only called in this one location), so it might as well be implied and not be explicitly passed in. BUG
seb-078 enm.c'241: What prevents another thread from getting a reference to this object after you've dropped the lock and before you blow it away by calling nwamd_object_fini()? I don't see how this is safe. Has this code been stress-tested? BUG
seb-079 enm.c'368-390: This code is identical to 304-323. This could be factored out into its own function. RFE
seb-080 enm.c'461: Need a block comment; check for what? BUG
seb-081 enm.c'572: Replace all of the "return (0);" calls in the above switch with proper "break;" calls, and you won't need this NOTREACHED lint comment. EXPLAIN
seb-082 enm.c'569: You don't need this default case. BUG
seb-083 enm.c'625: You unlock the object here, but proceed to read and write to its state afterwards. This doesn't look safe. BUG
seb-084 events.c'476,509: Stashing the user context like this is obsoleted by dtrace and mdb, and neither of those need to have debug enabled to work. Can we lose this? EXPLAIN/BUG
seb-085 events.c'477: s/returned/return/ BUG
seb-086 events.c'481,519,550,etc.: Since this isn't a PTHREAD_MUTEX_ERRORCHECK mutex, failure of pthread_mutex_lock() is impossible. BUG
seb-087 loc.c'201: Need block comment: check what? BUG
seb-088 loc.c'224,227: This would be simpler as:
  err = nwam_value_get_uint64(activationval, &activation);
  nwam_value_free(activationval);
  if (err != NWAM_SUCCESS) {
        nlog(...);
        return (0);
  }
BUG
seb-089 loc.c'349: This doesn't look right since another thread could be modifying active_loc. BUG
seb-090 ncu.c'51,1138: This doesn't look kosher at all. Basing functionality on link names is not correct. There looks to be some architecture missing here. ARCH/BUG
seb-091 ncu.c'191: Holding the link open is a problem for DR. This will need to eventually be addressed. This is a more general problem than just the DLPI interaction, obviously (I'm not sure how the existing rcm code interacts with nwamd's configuration of IP interfaces). The overall NWAM interaction with DR will need to be investigated fully in order for these two features to interoperate. Please file an RFE to track this. RFE/ARCH/BUG
seb-092 ncu.c'1427: It looks like some other thread can sneak in and grab a reference to this object after it's been unlocked and before it's blown away by nwamd_object_fini(). BUG
seb-093 ncu.c'1513-1528: This could all be collapsed:
  case NWAM_STATE_OFFLINE_TO_ONLINE:
  case NWAM_STATE_ONLINE_TO_OFFLINE:
  case NWAM_STATE_ONLINE:
        nwamd_ncu_state_machine(event->event_object);
        break;
BUG
seb-094 ncu.c'1545: Won't doing this after the object lock is dropped result in potential out-of-order issues with these calls? BUG
seb-095 ncu_ip.c'89: This function leaks both "request" and "reply". done
seb-096 ncu_ip.c'271: I think this needs to be newh. Otherwise, you're setting the broadcast on logical unit 0, and not the address that was created. BUG
seb-097 ncu_ip.c'540-582: The strategy used to figure out if a logical interface is needed or if it's the first address seems error prone and certainly not thread safe (although I'm not sure if thread safety is a concern for this function). This seems to be needed as a side-effect of the distinction between the newly introduced icfg_add_ipaddr() vs. icfg_set_addr() functions. It should be possible to fix this by defining a single icfg_add_addr() function that just does the right thing.
On a related note, why is one _ipaddr() and the other _addr()?
BUG
seb-098 ncu_ip.c'700: There's a XXX here. BUG
seb-099 ncu_ip.c'722: A cleaner interface would be two separate functions, a plumb function and an unplumb function. They can share the same implementation if necessary, but at least the callers won't be saddled with a huge ambiguous function name and needless boolean argument. BUG
seb-100 ncu_phys.c'69: The caller should pass in a buffer of size LIFNAMSIZ; there's no reason for this function to dynamically allocate memory. It could then return void and callers wouldn't need to handle failure. BUG
seb-101 ncu_phys.c'132: Similar to my comment on the plumb_unplumb() function, this really should be two functions whose names are indicative of what they do instead of one ambiguous one with a boolean argument that indicates what it should do. BUG
seb-102 ncu_phys.c'185: There's a XXX here. BUG
seb-103 objects.c'195: pthread_rwlock_wrlock() can't possibly fail. If it fails, then it's because there's a bug in your code and you might as well abort(). BUG
seb-104 objects.c'396: nwamd_object_fini() must not fail. It is called in a context where failure is not an option (there is no way to recover from such a failure). This must be rectified. It looks like every caller ignores the return value, so it looks like someone already knew that this was wrong... BUG
seb-105 util.c'241: Isn't this a little too late? zone_check_datalink() verifies if a link belongs to a running zone, but nwamd holds all links open when it starts, which is before zones boot. As such, the zone that needs this link won't be able to use it (a link's zone property can't be set if the link is open). I don't see how this works. Maybe I'm not seeing the bigger picture. How can an exclusive stack zone boot propertly while nwamd is running? BUG
seb-106 util.c'521: A safer model (one less prone to memory leaks) is one where the caller passes in an appropriately-sized buffer to store the answer. done

libnwam/netcfgd

Reviewer/ID Comment Status
meem-064 netcfgd'Unclear why this consists of multiple source files; it seems like everything could be consolidated into a single source file without sacrificing maintainability. done
meem-065 netcfgd/Makefile'29-30: Pulling in Makefile.lib seems wrong since that's for building libraries. Just use $(ROOT)/lib. done
meem-066 netcfgd/Makefile'35: Remove needless HEADERS definition. done
meem-067 netcfgd/Makefile'61: What does this $(ROOTCMD) dependency do? done
meem-068 netcfgd/util.h'Given that this only has logging functions, seems odd it's named util.h. (But then again, I can't figure out why this exists.) done
meem-069 netcfgd/util.h'33: Need a /* PRINTFLIKE2 */ here. done
meem-070 netcfgd/util.h'39: No externs, please. done
meem-071 netcfgd/logging.c'28-29: Unclear what this comment has to do with anything; no debug.c here. done
meem-072 netcfgd/logging.c'42: s/The idea for having this function is so that you can /This function allows you to/ done
meem-073 netcfgd/logging.c'43: s/Its/It's/ done
meem-074 netcfgd/logging.c'59: Why 256? Why not vasprintf()? done
meem-075 netcfgd/logging.c'81-90: Could be replaced with (in util.h)
          #define dprintf(...)     nlog(LOG_DEBUG, __VA_ARGS__)
done
meem-076 netcfgd/main.c'General: I can't figure out what the zonename code is for; we never seem to use the `zonename' variable. My nits below assume that somehow it's supposed to do something. done
meem-077 netcfgd/main.c'28: Comment should provide an overview of what this daemon does on a technical level. done
meem-078 netcfgd/main.c'32, 34, 38, 39, 40, et al: Superfluous #includes done
meem-079 netcfgd/main.c'51, 52: No excuse for these being globals. done
meem-080 netcfgd/main.c'57-59: Unclear what this comment has to do with anything. done
meem-081 netcfgd/main.c'68: Where does this code lookup SMF properties? done
meem-082 netcfgd/main.c'70: Where does this code manage privileges? done
meem-083 netcfgd/main.c'76: Is there a reason this uses LOG_NDELAY? done
meem-084 netcfgd/main.c'79-113: Someone really needs to put this in a library Looks like this is cut line-for-line from Nevada nwamd/main.c which in turn took it from pppoe/pppoed.c. done
meem-085 netcfgd/main.c'124: Prefer const. done
meem-086 netcfgd/main.c'126: No need to define `zoneid'; just inline the call to getzoneid() int the getzonenamebyid() call. done
meem-087 netcfgd/main.c'132: Why is it correct to charge on with GLOBAL_ZONENAME in this case? done
meem-088 netcfgd/main.c'141-142: Just curious: what exactly are we localizing? All of the messages here go to syslog which is not localized. done
meem-089 netcfgd/main.c'145: Why is this LOG_INFO? Seems like LOG_DEBUG. Also, LOG_PID was specified to openlog() so I'm not sure why this includes the pid as well. Finally, the message should be generated in start_logging(), not here. done
meem-090 netcfgd/main.c'149-155: Indenting here is one level off. done
meem-091 netcfgd/main.c'162: Comment states the obvious. done
meem-092 netcfgd/main.c'166-168: Unclear why we want to ignore USR1/USR2/INT. done
meem-093 netcfgd/main.c'170: Need to resolve this XXX for SIGTHAW. done
tony-15 I have another concern regarding location-based IPfilter configuration. The current implementation requires users to supply a customized ipf rules for every location if they want to configure IPfilter. This essentially undo the functionality of Host-based firewall which simplified IPfilter configuration. We ought to allow users to configure location with the option of using their existing IPFilter configuration, in fact, I'd argued that option should be the default.  
sowmini-03 it's hard to figure out which libnwam interfaces are "truly" exported, and which ones are there because they are shared between some daemon and libnwam. The nwam_backend_init is an example of the latter, which ends up in mapfile-vers as globally exported just so that the daemon can also use it. We need to find a better solution for the latter case (see comments for libnwam.h)  
sowmini-04 netcfgd/Makefile: dlmgmtd runs as OWNER dladm, group sys. What are the owner/group of netcftd (I'd guess that the owner would be netcfg- but inside the code it seems to use netadm, and invokes getpwam etc. - why the divergence from dlmgmtd)? DISCUSS (thread)
sowmini-05 netcfgd/Makefile: do we need to define ROOTCFGDIR/<configfile> permissions?  
sowmini-06 netcfgd/logging.c: see relevant comments for netcfgd/main.c  
sowmini-07 netcfgd/main.c: fg can be a local variable to main() - it is not used outside the main() context.  
sowmini-08 netcfgd/main.c: debug doesn't need to be extern global, it can be static to logging. but perhaps it is not needed at all? How is one supposed to set it? (One suggestion, always have syslog support, but use SIGUSR1/SIGUSR2 handlers to make it more/less verbose by incr/decr debug)  
sowmini-09 zonename does not need to be a global var: it's only usage is for lookup_zonename, and there it is passed as an argument.  
sowmini-25 linbwam/Makefile: ok except for similar question about the check target as for inetcfg/Makefile  
sowmini-26 libnwam_audit.c'69: do you need to adt_free_event() and adt_end_session()?  
sowmini-27 libnwam_audit.c'49: do you need to adt_end_session()?  
sowmini-28 libnwam_backend.c: how does nwam_backend_door_server work (doesn't it end up doing door_return 2 times?): on receiving some NWAM_BACKEND*REQ, it sets up cmd = NWAM_BACKEND_*RES, and then goes to nwam_create_backend_door_arg which will do a door_return at line 181. Then nwam_backend_door_server() will again do a door_return at line 325, right?  
sowmini-29 libnwam_backend.c'nwam_backend_init(): lines 349-360. dlmgmtd had some issues with the filesystem not being writable early in boot. How does nwamd work around that problem?  
sowmini-30 libnwam_backend.c'382: if fattach() fails, we should door_revoke() the DOOR_FILE.  
sowmini-31 libnwam_backend.c: nwam_backend_exit() is something that is only used by netcfgd, and it registers an atexit() callback, so it doesn't look like it belongs in a general "libnwam/common" file.. this should be made local to netcfgd/*.c itself.  
sowmini-32 libnwam_backend.c: should this be 0755
    358             (chmod(NWAM_DOOR_DIR, 07555) < 0 ||
 
sowmini-33 libnwam_backend.c: make_door_call() is a rather generic function name (and libscf also has this). Suggest nwam_make_door_call() or nwam_door_call() instead.  
sowmini-34 libnwam_impl.h: please use unique prefixes for fields to aid cscope. e.g, use nwh_ as the prefix for fields in struct nwam_handle, nwv_ for struct nwam_value fields. Just the simple "name" field is currently used in 5 different structures even withing libnwam_impl.h itself.  
sowmini-35 libnwam_impl.h: nit:
    56  struct nwam_value
    57  {
  should be collapsed to one line:
    56  struct nwam_value {
 
sowmini-36 libnwam_impl.h: please add some comments explaining what the various fields in nwam_backend_door_arg are (e.g., arg_parent, arg_object etc.) and what the layout of the data passed between client and server looks like  
sowmini-37 libnwam_impl.h'370: nit: s/ist/list  
sowmini-38 libnwam_files.c'value_add_escapes(): instead of repeatedly doing malloc/free around this function, the caller can pass in the output array with its size. another alternative is for value_add_escapes() to create out by doing a strdup(in) similarly for value_remove_escapes()  
sowmini-39 libnwam_enm.c'nwam_enm_handle_create: is this function live? it's not exported via mapfile-vers or libnwam.h, and there are no internal calls to it? Functions that seem to need it (e.g., nwam_enm_read) seem to eventually create the handle by calling nwam_handle_create itself. If it's not needed, nwam_enm_handle_create should be removed.  
sowmini-40 libnwam_enm.c'nwam_enm_set_name(), nwam_enm_get_prop_type() also appear dead.  
sowmini-41 libnwam_enm.c:How does nwam_enm_handle_create verify its args (e.g., that name is null terminated, non-null etc)? Same question applies to nwam_enm_read() which is exported, so could get anything for its args. Minimally it should take a name_size argument in addition to the char *name. Sanity checking of flags wold also be a good thing.  
sowmini-42 libnwam_known_wlan.c'nwam_known_wlan_handle_create()  
sowmini-43 libnwam_loc.c'nwam_loc_handle_create(): is this function live? not exported, and no calls to it? See comments for libnwam_enm.c  
sowmini-44 libnwam_loc.c'nwam_loc_validate(): where is char *name freed?  
sowmini-45 libnwam_loc.c'325-331: please move these definitions to the start of the file- they seem to be sprouting in random places.  
sowmini-46 libnwam_ncp.c: nwam_ncp_get_read_only() leaks char *name done
sowmini-47 libnwam_object.c: please add comments before each function, explaining input/output and expected returns from these functions. The "parent" term, for example, is not inutitive- it seems like this is the name of the configuration file/db from which the backend is supposed to read/write- is that correct? If yes, it would be more obvious to rename "parent" to "dbname" or "conf_file". Using the term "parent" for this makes it sound like there would be a related "child", which is not the case here (for file-store).  
sowmini-48 libnwam_object.c'1445-1460 please move these definitions to the start of the file  
sowmini-49 libnwam_object.c'1768-1769: why have NWAM_IP_VERSION_IPV4/NWAM_IP_VERSION_IPV6 when IPV4_VERSION and IPV6_VERSION are available?  
sowmini-50 libnwam_object.c: doesn't valid_link_mtu have to check if the mtu is within the acceptable range for the link? More generally, I would think that the signature of the prop_validate function would need more args to verify against libdladm, etc.?  
sowmini-51 libnwam.h: what is NWAM_FLAG_GLOBAL_MASK used for? Should this just be "-1"?  
sowmini-52 libnwam.h: why the extra level of indirect for NWAM_WALK_FILTER_MASK? Can't we just have "#define NWAM_WALK_FILTER_MASK (0xFFFFFFFFULL << 32)"  
sowmini-53 libnwam.h: use parentheses around NWAM_FLAG_NCU_TYPE_LINK, NWAM_FLAG_NCU_TYPE_INTERFACE But a bigger question is - why are these being shifted out by 32 (i.e., what's in the low order bits, and why is it so complex?)  
sowmini-54 libnwam.h: need parentheses around NWAM_FLAG_NCU_CLASS_* definitions. But the class definitions are confusing: on the one hand PHY and IPTUN seem to be a subset of datalink_class_t (and therefore mutually exclusive), but then there's CLASS_IP (which applies to any datalink_class_t). How are distinctions drawn here? At the very least, some comments would be needed to explain when/how these should be specified.  
sowmini-55 libnwam.h: it's unfortunate that nwam_backend_init and nwam_backend_fini are exposed as global interfaces to any application that links libnwam, when really, all that's needed is to share them between libnwam and netcfgd. I'm not sure if SUNWprivate can be used here , but one other option is to pull the related functions into a file (seems to be libnwam_backend.c in this case) and link the file separately into libnwam and netcfgd (e.g., see the usage of $SRC/common/net/patricia/radix.c in $SRC/cmd/ipf/tools/Makefile.tools where the same code is shared between the kernel ip module and ipfilter . This will allow the functions themselves to be declared static, but bug fixes in the code will be automatically picked up by both users, without exposing the interface to other library callers.  
sowmini-56 nwam_addrsrc_t: fyi, Brussels is introducing similar definitions. Perhaps it would be useful to extract this to a common file that can be shared by both libraries (and without any NWAM_* prefix)?  
sowmini-57 NWAM_STATE*STRING definitions do not have to be exposed via libnwam.h: should be mapped using a {code, string} array line nwam_errors that's used by nwam_state_to_string(); see related comments about libnwam_util.c. The same thing applies to
  nwam_aux_state_t, NWAM_AUX_STATE*STRING,
  nwam_activation_mode_t, NWAM_ACTIVATION_MODE_*STRING,
  nwam_condition_t, NWAM_CONDITION*STRING,
  nwam_condition_object_type_t,  NWAM_CONDITION_OBJECT_TYPE*STRING
  nwam_configsrc_t, NWAM_CONFIGSRC_*STRING
  nwam_nameservices_t, NWAM_LOC_PROP*
  nwam_ncu_type_t, NWAM_NCU_TYPE*STRING
  nwam_ncu_class_t, NWAM_NCU_CLASS_*STRING
  nwam_iptun_type_t, NWAM_IPTUN_TYPE*STRING
  nwam_addrsrc_t, NWAM_ADDRSRC*STRING,
  nwam_priority_mode_t, NWAM_PRIORITY_MODE*STRING
 
sowmini-58 nwam_iptun_type_t can just use clearviews' iptun_type_t?  
sowmini-59 libnwam_util.c: the nwam*_to_string functions should use {code, string} arrays like nwam_errors[]. In fact, there can be one nwam_code_to_string_internal() that takes the {code, string} array and code as args, and returns the const char * as the result. Then the nwam_code_to_string_internal() (which would be a generalized version of nwam_strerror()) could be shared by nwam_object_type_to_string etc. and this would also consolidate the dgettext calls.  
seb-107 libnwam_events.c'284: Block comment needed: what does this do?  
seb-108 libnwam_ncp.c'553: Having the caller pass in a buffer and buffer length is a better model, as it is less prone to memory leaks.  

CLI (nwamcfg, nwamadm) (Anurag) [nwamadm thread, nwamcfg thread]

Reviewer/ID Comment Status
meem-004 nwamadm/Makefile'Given the way gettext() is used in nwamadm, you need something like XGETFLAGS += -a -x $(PROG).xcl and an nwamadm.xcl file. done
meem-005 nwamadm/Makefile'34: Why is LFLAGS set in here? done
meem-006 nwamadm/Makefile'36: -I. is wrong; local header files should be included with `#include "local.h"'. done
meem-007 nwamadm/Makefile'30: Needless; source is only built from one file. done
meem-008 nwamadm/Makefile'42-44: Needless rules. done
meem-009 nwamadm/Makefile'55: Why not use lint_PROG? done
meem-010 nwamadm.c'Throughout: the ofmt API needs to be used to print stuff out rather than rolling your own printing logic. This will also provide parsable mode and user-selectable fields for free (which currently seem to be missing). RFE
meem-011 nwamadm.c'Throughout: what's up with the name zerr()? Am I to assume it's because this code started life as zoneadm.c? Seems like it should be called die(), and seems like you could also use a die_nwamerr() function that takes a nwamerr and does the nwam_strerror() a la die_dlerr() in dladm. done
meem-012 nwamadm.c'Throughout: seems a shame that the libnwam walker APIs require a non-NULL cb_ret argument, as nothing here seems to want to consult it. Why not allow it to be NULL? RFE
meem-013 nwamadm.c'50: Needless blank line. done
meem-014 nwamadm.c'58, 64-72: The use of both command numbers and an array of command entries seems muddled. Seems like all the functionality tied to command numbers could be folded into state tracked in the command entries – e.g., a cmd_help pointer-to-function (or just a simple const char *), and a flags field that indicates whether e.g. "-x" can be used or whether the type needs to be determined. done
meem-015 nwamadm.c'60: Should be cmd_handler for consistency. done
meem-016 nwamadm.c'60: Should define a typedef for this – e.g.:
                typedef int (cmd_handle_func_t)(int, char **);

... then declare cmd_handler as a pointer to this, and the declarations on 79-84 as instances of this type.

done
meem-017 nwamadm.c'77: Seems like this FMRI should be in a library header. done
meem-018 nwamadm.c'151: Unclear why this is a global; seems like it should be declared in interact_func() and passed to eventhandler(). done
meem-019 nwamadm.c'167-277: I'd expect these helper routines to be in libnwam rather than nwamadm. Some of them already appear to be there, such as nwam_ncu_type_to_flag(). Why are they here? done
meem-020 nwamadm.c'179, 193, 215, 230, 246, 262, 275, 297: The default cases here seem unhelpful. I'd expect strings of "?" and enumerations along the lines of NWAM_OBJECT_TYPE_UNKNOWN. done
meem-021 nwamadm.c'209: Presumably this should be "ncu"? done
meem-022 nwamadm.c'323: Presumably this should be ""%s: <subcommand>". done
meem-023 nwamadm.c'368, 371: This seems like abuse of return values, as NWAM_WALK_HALTED and NWAM_SUCCESS do not appear to be intended for this use. Instead,
it seems that the walker should return 0 or 1.
done
meem-024 nwamadm.c'378: Why is it safe to ignore the return value from this function? Is it that we assume `state' will only be modified by this function call upon success? Seems a needless assumption. done
meem-025 nwamadm.c'451: Would seem more natural to return `type' and remove the `num' parameter in place of an NWAM_OBJECT_TYPE_UNKNOWN value. done
meem-026 nwamadm.c'514: This seems unnecessarily obscure; don't we know cmd_to_str(CMD_LIST) == "list"? done
meem-027 nwamadm.c'549-558: Seems like this would just be:
          if (cmd_num != CMD_LIST && type == NWAM_OBJECT_TYPE_NONE)
done
meem-028 nwamadm.c'560: Needless cast. done
meem-029 nwamadm.c'653-684: This should be factored out into a funciton that takes the type and then is merely called here for NWAM_NCU_TYPE_LINK and NWAM_NCU_TYPE_INTERFACE. For bonus points, could take a function pointer which would be either &nwam_ncu_enable or &nwam_ncu_disable. done
meem-030 nwamadm.c'651, 690, 693: Should be a switch statement with NWAM_SUCCESS, NWAM_ENTITY_MULTIPLE_VALUES and default. done
meem-031 nwamadm.c'705-715: Can factor this out to a function and reuse this code with disable_func(). For I18N to work, you need to restructure the messages – e.g.: "cannot enable: <blah>" – then you'll end up parameterizing the subcommand name (which won't be translated). done
meem-032 nwamadm.c'719: By the time we get here isn't the enable complete? That is, seems like this should be "Enabled", not "Enabling". done
meem-033 nwamadm.c'724: `if' block should be replaced with assert(ret != NWAM_SUCCESS)' and the code should be unindented. done
meem-034 nwamadm.c'785-868: See previous comments regarding enable_func() code. done
meem-035 nwamadm.c'871: Would seem preferable to return a error code indicating whether the function succeeded rather than overloading *_UNINITALIZED for the job. done
meem-036 nwamadm.c'872, 934: Everything that uses determine_object_state() immediately then calls add_to_profile_entry(). Seems like it would be simpler to have add_to_profile_entry() get the state itself rather than taking `state' and `auxstate' arguments. done
meem-037 nwamadm.c'928: How do we get here? Seems like we should assert(0). done
meem-038 nwamadm.c'932: p_entries is a linked list, not an array. done
meem-039 nwamadm.c'956: p_last_entry is gross. Does the order of the list matter? If not, why not prepend to the list? If so, would prefer to make the list circular and use p_prev. done
meem-040 nwamadm.c'979, 1020, 1058, 1090: Needless cast. done
meem-041 nwamadm.c'986, 988: `name' appears to be leaked. done
meem-042 nwamadm.c'988: `val' appears to be leaked. done
meem-043 nwamadm.c'1108-1156: See previous comments about using ofmt. As an aside, the field names are generally considered part of the command itself and are not something we translate – and this is important when -o <field> is supported. RFE
meem-044 nwamadm.c'1165-1166: Needless "optimization". done
meem-045 nwamadm.c'1196-1199: No voodoo code, please. done
meem-046 nwamadm.c'1207, 1219, 1227, 1234: Needless cast. done
meem-047 nwamadm.c'1250, 1251: Useless comments. done
meem-048 nwamadm.c'1260-1475: This function is really hard to read – and again, ofmt should be used to print output. RFE
meem-049 nwamadm.c'1260-1475: Is this intended as a debugging aid or something that end-users would actually use? If the latter, seems like some I18N handling is missing in the various prompts. Also, how is the end-user supposed to make sense of the stuff output from this? Further, it seems odd to me that the interactive support and event monitor have been glommed together into one facility. done
meem-050 nwamadm.c'1266: `action' should be declared properly as a `const char *' and the bogus casts on line 1278, 1422, and 1449 should be removed. done
meem-051 nwamadm.c'1338, 1346, 1388: This works without fflush(stdout)? done
meem-052 nwamadm.c'1338, 1346, 1388: Can the user ^C out? If so, how does that work? If not, seems a usability problem. done
meem-053 nwamadm.c'1366, 1402: Why are errors going to stdout? done
meem-054 nwamadm.c'1378, 1388: Would expect a space after the ":". done
meem-055 nwamadm.c'1432: How do you know this is a sockaddr_in? Sure looks like this code can be reached with a sockeddr_in6. done
meem-056 nwamadm.c'1474: Remove blank line. done
meem-057 nwamadm.c'1511: See previous comment about I18N with field names. done
meem-058 nwamadm.c'1515-1528: Odd code here seems to stem from mixing interaction and event monitoring. done
meem-059 nwamadm.c'1543: strdup() can fail. This is the problem with using basename(3C) rather than just doing the typical:
          if ((execname = strrchr(argv[0], '/')) == NULL)
                execname = argv[0];
          else
                execname++;

You can also remove the <libgen.h> #include and -lgen link.

done
meem-060 nwamadm.c'1551-1554: This means one cannot observe the events at NWAM startup with "interact" which seems unfortunate. done
meem-061 nwamadm.c'1531: So using the "interact" subcommand always exits with a non-zero status? done
meem-062 nwamadm.c'1547, 1554, 1565: Would be clearer as EXIT_FAILURE. done
meem-063 nwamadm.c'1556: I suppose it doesn't matter much, but `state' is leaked. done
meem-109 nwamcfg.c: many of the same comments I made for nwamadm apply to this file – e.g., zerr(), die_nwamerr(), CMD_* vs command tables, etc. In the interest of brevity, I have not repeated previous comments that apply directly to nwamcfg (e.g., problematic use of basename()). added, no exit() though
meem-110 nwamcfg.c: a lot of very repetitious code – I have enumerated a number of instances below. FWIW, a lot of these issues are due to the libnwam API itself – e.g., sets of parallel functions that differ only in the handle they take and their name. It seems like an OO design would've simplified the code considerably – e.g., each object could've had an ops vector associated with it that the various callers could use without repeatedly concerning themselves with the type of the object. cleaned up
meem-111 nwamcfg.c: because of the above, I have mostly focused on smaller opportunities for code cleanup. That is, I find the libnwam API problematic because it leads to rampant duplication and code sprawl for consumers like nwamcfg, but aside from a couple of examples to explain what we could be done "someday" I have avoided commenting on it unless I have a specific and straightforward suggestion for streamlining the code. done
meem-112 nwamcfg.c: assorted uses of printf() without localization. (e.g., 918-920, 1984, 3060, 4331, 4335, ...) no need
meem-113 nwamcfg.c: assorted spurious ARGSUSED directives – e.g.: 3051, 3076, 3101, ... done
meem-114 nwamcfg.c: the various got_*_handle globals seem unnecessary; shouldn't we be able to just check if the handles are NULL? done
meem-115 nwamcfg.c: numerous calls to check_scope() could be more simply handled by the function dispatcher, rather than repeated in each *_func(). done
meem-116 nwamcfg.c: several blocks of code have something like:
          if (got_enm_handle) {
              prop_type = pt_to_prop_type(pt_type, NWAM_OBJECT_TYPE_ENM);
              if (prop_type == NULL)
                      goto prop_error;

              /* check if property can be set */
              if (is_prop_read_only(prop_type, NWAM_OBJECT_TYPE_ENM))
                      goto read_only;
              if (!show_prop_test(prop_type, enm_prop_display_entry_table,
                  NWAM_OBJECT_TYPE_ENM))
                       goto skip_prop;
              /* ... */
          } else if (got_wlan_handle) {
              prop_type = pt_to_prop_type(pt_type,
                  NWAM_OBJECT_TYPE_KNOWN_WLAN);
              if (prop_type == NULL)
                      goto prop_error;

              /* check if property can be set */
              if (is_prop_read_only(prop_type, NWAM_OBJECT_TYPE_KNOWN_WLAN))
                      goto read_only;
              if (!show_prop_test(prop_type, wlan_prop_display_entry_table,
                  NWAM_OBJECT_TYPE_KNOWN_WLAN))
                      goto skip_prop;
              /* ... */
          } else if (got_ncu_handle) {
              /* ... */

This code could be simplified significantly if there was a function that consulted the various handles to determine which one was live and returned the appropriate object type. Then you could do something like:

          handle_type = get_handle_type();
          if ((prop_type = pt_to_prop_type(pt_type, handle_type)) == NULL)
                goto prop_error;
          if (is_prop_read_only(prop_type, handle_type))
                goto read_only;
          if (!show_prop(prop_type, prop_table[handle_type], handle_type))
                goto skip_prop;

... and only switch on the handle_type once you need to get into logic that cannot easily be parameterized.

done, added active_object_type()
meem-117 nwamcfg.c'32: I don't see any block comments near the end of nwamcfg_grammar.y. removed reference
meem-118 nwamcfg.c'163, 167, 187, 189, 193, 214: What is the significance of these comments? removed
meem-119 nwamcfg.c'219, 228, 236: Why are these arrays NULL-terminated? removed
meem-120 nwamcfg.c'240, 286, 304, 359: Why are these all different structures? They all have identical contents and field names. These should be folded into a common nwamcfg_prop_table_entry structure and all members should have a consistent prefix for easy cscoping. done
meem-121 nwamcfg.c'399: Seems like `output_file' could be local to export_func() and passed to the various walker callbacks via the walker callback argument. done
meem-122 nwamcfg.c'405: Seems like quoted_strings could just be an argument to output_prop_val(). done
meem-123 nwamcfg.c'447, 451, 455: Indeed, errors need to be reported. done
meem-124 nwamcfg.c'483: Doesn't seem to have anything in particular to do with strings – would expect `array_free(void **array, int nelem)'. done
meem-125 nwamcfg.c'962-986: Assumes English locale. done
meem-126 nwamcfg.c'1043: prompt[] only accounts for MAX_NWAM_TYPE_LEN once, but there can be two types. done
meem-127 nwamcfg.c'1084: Why is it safe to ignore the return value from string_to_yyin()? not ignored
meem-128 nwamcfg.c'1218-1265: Should be condensed to a single is_prop_listprop() function that takes the table pointer. (That said, I would've expected this attribute to be part of the object itself and thus tracked by libnwam rather than nwamcfg.) moved to libnwam
meem-129 nwamcfg.c'1355-1378: Mapping between NWAM classes and NWAM object types seems more suited to libnwam. moved
meem-130 nwamcfg.c'1390-1392: Under what situations do callers pass in NULL? export_func(), list_func()
meem-131 nwamcfg.c'1396, 1398: Crashes if strdup() fails. done
meem-132 nwamcfg.c'1418-1659: Most error paths in this function leak `newname'. done
meem-133 nwamcfg.c'1459-1519: Handling of `ret' can be centralized (cmd_res1_type and cmd_res2_type can be converted to strings if precise error messages are desired). done
meem-134 nwamcfg.c'1525-1625: Lots of repetitious parallel logic here. This is exactly the kind of code that would be simple and clear had libnwam associated an ops vector with its objects rather than having a set of equivalent but distinctly-named methods for every operation. done
meem-135 nwamcfg.c'1654-1655, 1925-1926, 1977-1978, 4859-4860, 2140: Shouldn't alloc_cmd() be able to guarantee this? done
meem-136 nwamcfg.c'1664: nit: s/than/the. done
meem-137 nwamcfg.c'1671-1738: Logic to process the return codes should be shared across these functions – e.g.:
          int
          destroy_ncp_callback(nwam_ncp_handle_t ncp, void *arg)
          {
                return (destroy_ret(nwam_ncp_destroy(ncp,
                   NWAM_FLAG_DO_NOT_FREE));
          }
done
meem-138 nwamcfg.c'1752-1764: What happens to nwamcfg when this to fails part-way through? continues
meem-139 nwamcfg.c'1778-1783: Given the way this function is used, it would seem simpler to change this be have_ncus() { return (1) } and have the caller check if the NWAM_WALK_HALTED was returned to determine whether or not the list was empty. code removed
meem-140 nwamcfg.c'1896: If nwam_ncp_walk_ncus() fails, it appears we delete the ncp regardless. code removed
meem-141 nwamcfg.c'1935-1955: Duplicates logic in cancel_func(). factored out
meem-142 nwamcfg.c'1973-1982: Duplicates logic in end_func(). factored out
meem-143 nwamcfg.c'2019-2052: Should be backed by a common implementation that takes a propname – but moreover, I'd expect these utility routines to be provided by libnwam. moved
meem-144 nwamcfg.c'2028, 2030, 2046, 2048: Returning -1 seems incorrect since it's out-of-range for the type. Would seem simplest to add e.g. NWAM_NCU_TYPE_UNKNOWN to the enums. done
meem-145 nwamcfg.c'2143, 3577: nit: Superfluous `return'. removed
meem-146 nwamcfg.c'2201, 2221: Leaks `name'. done
meem-147 nwamcfg.c'2223: nit: Superfluous blank. removed
meem-148 nwamcfg.c'2240-2344: This logic could be shortened considerably by having the table pointers stored in an array that's keyed by the type – i.e.:
          int
          prop_to_pt(const char *nwam_prop, nwam_object_type_t type)
          {
                nwam_prop_table_t *table;

                assert(type >= 0 && type < NWAM_OBJECT_TYPE_KNOWN_WLAN);
                table = prop_tables[type];

                for (i = 0; table.prop_type != NULL; i++) {
                        if (strcmp(nwam_prop, prop_table[i].prop_type) == 0)
                                return (prop_table[i].type);
                }
                return (-1);
          }
done
meem-149 nwamcfg.c'2352: Why is that a reason for cutting and pasting this function? removed, use from library
meem-150 nwamcfg.c'2389-2399: Doesn't strtol() already provide this ability by checking if isdigit(*endptr)? done
meem-151 nwamcfg.c'2406: Why is `input_str' `const char *'? Doesn't seem like this function treats it as const (as per the logic on 2432-2443). done
meem-152 nwamcfg.c'2453-2467: val[] array is leaked. done
meem-153 nwamcfg.c'2543-2544: How will this value be maintained? Seems like nothing uses more than two values though. maintained here
meem-154 nwamcfg.c'2777-2780: `return (!prop_found)' seems simpler (if the concern is clarity, giving the boolean another name (like `show_prop') would help. keeping it as show_prop
meem-155 nwamcfg.c'2843: If there are none then why do we check? done
meem-156 nwamcfg.c'2923-3018: See previous comments regarding get_handle_type() for how this could be streamlined. done
meem-157 nwamcfg.c'3051-3151: Not to harp on this too much, but this is another instance where one really pines for an ops vector – e.g.:
          int
          list_obj_callback(nwam_obj_t *obj, void *arg,
              const char *objname, const char *objplural)
          {
                 char           *name;
                 nwam_error_t   ret;
                 boolean_t      *list_msgp = arg;

                 if (*list_msgp) {
                         (void) printf("%s:\n", objplural);
                        *list_msgp = B_FALSE;
                 }

                 ret = (*obj->namefunc)(obj, &name);
                 if (ret != NWAM_SUCCESS) {
                        warn_nwerr("List error: cannot get %s", objname);
                        return (1);
                 }

                 (void) printf("\t%s\n", name);
                 free(name);
                 return (0);
          }

          ... then e.g.:

          int
          list_enm_callback(nwam_enm_handle_t enm, void *arg)
          {
                return (list_obj_callback(enm, arg, "ENM", "ENMs"));
          }
done
meem-158 nwamcfg.c'3181-3258: This is really hard to read. One minor improvement would be to have the logic at 3193-3257 just build the string arrays, and have a single loop iterate through them at the end and centralize the fprintf() and NWAM_VALUE_DELIMITER_STR logic. done
meem-159 nwamcfg.c'3322-3334: Needs to share a common implementation with output_propname(). done
meem-160 nwamcfg.c'3322-3334: Shouldn't bisect the *_listprop() routines. done
meem-161 nwamcfg.c'3431, ...: nit: Why is list_msg local to each `if' clause? done
meem-162 nwamcfg.c'3556-3558: Why is this needed? done
meem-163 nwamcfg.c'3564: Shouldn't list_ncu_callback() already print this? code removed
meem-164 nwamcfg.c'3573, 4120: Superfluous check. done
meem-165 nwamcfg.c'3581-3590, 3671-3681, 3717-3727, 3769-3779: Functions can easily be consolidated into a single function that takes a type. done
meem-166 nwamcfg.c'3830-3832: L1 exports would be cleaner to implement as an export[] array indexed cmd_res1_type – e.g. 3915-3937 would essentially be:
                if (cmd->cmd_res1_type == RT1_UNKNOWN) {
                        for (i = RT1_MIN; i < RT1_MAX; i++)
                                export_l1[i] = B_TRUE;
                } else {
                        export_l1[cmd->cmd_res1_type] = B_TRUE;
                }
done
meem-167 nwamcfg.c'3888: Short comment explaining the purpose of the write_to_file check would be helpful. done
meem-168 nwamcfg.c'4166-4191: See previous comments about get_handle_type(). done
meem-169 nwamcfg.c'4244-4275: See previous comments about get_handle_type(). done
meem-170 nwamcfg.c'4296: How can we get here with prop_type != NULL? done
meem-171 nwamcfg.c'4343-4611: Significant amount of duplicate code here that should be refactored – e.g., lines 4356-4362, 4426-4432, 4493-4500, 4568-4574 all identical (and seems like functionality that could partially be built into output_prop_val()), and much of the user input processing could be factored out to a common function and parameterize based on the type. done
meem-172 nwamcfg.c'4338-4340: Seems more complex to do it this way than to just have 4332 and 4335 print the closing brace. done
meem-173 nwamcfg.c'4621-462: nits: s/new/newly/, s/value/a value/, s/current/the current/ done
meem-174 nwamcfg.c'4659-4770: Duplicate walking logic should be factored out. factored out
meem-175 nwamcfg.c'4830: Indeed, an error here would be good. done
meem-176 nwamcfg.c'4839-4852: Essentially duplicates the logic from 1084-1095. factored out
meem-177 nwamcfg.c'4899-4908: What would go wrong if we attempted to use a file that wasn't a "regular file"? error
meem-178 nwamcfg.c'4854-4865: Duplicates logic in end_func(). factored out
meem-179 nwamcfg.c'4918-4925: Duplicates logic in destroy_func(). factored out
meem-180 nwamcfg.c'4959: Shouldn't cmd_file_mode already be B_FALSE? done

SMF (Anurag) [post 1, post 2]

Reviewer/ID Comment Status
paul-02 net-loc'265: do_nis(): Keep in mind that the ypservers, if listed by name, need to be in /etc/hosts. NIS looks explicitly there and does not so regular nameservice lookup. Not sure if this is really the place to address it, but there probably should be some warning when the user is doing manual config and uses a hostname. done
paul-03 net-loc'399: It would probably be good to not use the default nsswitch.nis file. Especially if you have both dns and NIS enabled. In general, one only needs NIS for passwd and automount (and possibly printers). At the very least, it would be good to have hosts and ipnodes list dns first, if available. done
paul-04 net-nwam:revert_to_legacy_loc() disables IPsec policy and IPfilter policy, changes some properties, then re-enables them. This leaves open a window of opportunity where there is no network security policy, which is a bad thing. Can't you change the config file locations in the SMF properties and do a refresh/restart instead without first disabling? Or refresh/restart/innocuous enable in case the service wasn't started before? done
tony-01 The integration of 6855845, Allow Property Modification in SMF profiles, into b119 should be sufficient for NWAM phase next to quickly update location specific values and simplify logic in various services and their inter-relationships. nothing to do
tony-02 Is there a reason why /etc/svc/volatile is used instead of /var/run or a non-persistent pg? explained, no specific reason
tony-03 ipf, ipf6 files: Comments on line 3 and 16 suggest these files aren't the final version. done
tony-04 usr/src/cmd/svc/milestone/network-service.xml - No update? However, are dependencies (e.g. NIS dependencies) and comments still accurate if the service is now only responsible for updating DNS information? undid unnecessary changes
tony-05 network-physical.xml'41,87 - It's not clear from the design spec that there will be additional network/physical instances. Clarification please? explained, code fixed
tony-06 network-physical.xml'74 - unnecessary diff? done
tony-07 network-location.xml'100-113 manifest-import is defined as a dependent but the comment states it should be a dependency. Has testing been done to verify correct behavior? done
tony-08 svc method scripts: These files have similar implementation to figure out whether a service is enabled. It's probably better to have define a single service_is_enabled() in net_include.sh that these three files can consume. done
tony-09 create/revert_legacy_loc doesn't correctly save/restore custom file. User may have a policy other than custom but has a valid configuration file. The current code doesn't correctly save the configuration file if policy is something other than 'custom' thus can't properly restore it.  
tony-10 net-loc'501 - clearing custom policy_file is probably unnecessary since policy is set to 'none'. done
tony-11 net-loc'502 - refresh_ipf also needs to be set here to make the changes effective. done
tony-12 net-loc'stop_svc() - in all uses of this function, no configuration change was made to the target service so a refresh isn't necessary. done
tony-13 net-loc'refresh_svc() - The name seems incomplete as the function really is refreshing/starting the service with the updated configuration. Perhaps run_svc? done
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

Sign up or Log in to add a comment or watch this page.


The individuals who post here are part of the extended Sun Microsystems community and they might not be employed or in any way formally affiliated with Sun Microsystems. The opinions expressed here are their own, are not necessarily reviewed in advance by anyone but the individual authors, and neither Sun nor any other party necessarily agrees with them.

Copyright 1994-2009 Sun Microsystems, Inc.
Powered by Atlassian Confluence
Sun Guidelines on Public Discourse Privacy Policy Terms of Use Trademarks Site Map Employment Investor Relations Contact