M MODULE/SystemTypes.pmod/Generic.pike +20 -0
@@ 1,11 1,31 @@ 
 import Protocols.DHCPv6;
 
+string preamble = "\n#\n# BEGIN DHCPv6_PD Managed segment\n#\n";
+string postamble = "\n#\n# END DHCPv6_PD Managed segment\n#\n";
+
 object config;
 
 protected void create(object _config) {
   config = _config;
 }
 
+string get_command_segment(string conf) {
+  string seg;
+  sscanf(conf, "%*s" + preamble + "%s" + postamble + "%*s", seg);
+  return seg || "";
+}
+
+string remove_command_segment(string conf) {
+  string pre, post;
+  sscanf(conf, "%s" + preamble + "%*s" + postamble + "%s", pre, post);
+  return (pre||"") + (post||"");
+}
+
+mixed get_config_value(string property_name, mixed default_value) {
+  if(has_index(config, property_name)) return config[property_name];
+  else return default_value;
+}
+
 string get_identifier();
 void prefix_acquired(IA_PDOption allocation, int has_changed, IA_PDOption old_allocation);
 void prefix_abandoned(IA_PDOption allocation);

          
M MODULE/SystemTypes.pmod/MacOS.pike +16 -26
@@ 2,59 2,49 @@ import Protocols.DHCPv6;
 
 inherit .Generic;
 
-string preamble = "\n#\n# BEGIN DHCPv6_PD Managed segment\n#\n";
-string postamble = "\n#\n# END DHCPv6_PD Managed segment\n#\n";
+// System specific module for use on MacOS systems with launchd and rtadvd.
+// Other BSDs also use rtadvd, so that portion of the code could be used
+// on those systems as well.
 
-string ndpdconffile = "/etc/inet/ndpd.conf";
+string service = "system/rtadvd";
+string conffile = "/etc/rtadvd.conf";
 
 string get_identifier() {
-//  if(file_stat("/etc/dhcp/duid"))
-//    return Stdio.read_file("/etc/dhcp/duid");
-//  else 
   string uuid;
   sscanf(Process.popen("ioreg -d2 -c IOPlatformExpertDevice | grep IOPlatformUUID"), "%*s = \"%s\"", uuid);
   return uuid;
 }
 
-string get_command_segment(string conf) {
-  string seg;
-  sscanf(conf, "%*s" + preamble + "%s" + postamble + "%*s", seg);
-  return seg || "";
-}
-
-string remove_command_segment(string conf) {
-  string pre, post;
-  sscanf(conf, "%s" + preamble + "%*s" + postamble + "%s", pre, post);
-  return (pre||"") + (post||"");
-}
-
 void prefix_acquired(IA_PDOption allocation, int has_changed, IA_PDOption old_allocation) {
 werror("prefix_acquired(%O, %O, %O)\n", allocation, has_changed, old_allocation);
 
 // TODO we need to come up with a better mechanism for writing configuration.
-   string conf = Stdio.read_file(ndpdconffile) || "";
+   string conf = Stdio.read_file(conffile) || "";
    string cs = get_command_segment(conf);
 werror("Old conf: %O\n", cs);
-   string ncs="\nprefix " + allocation->address + "/" + allocation->prefix + " " + config->downstream_interface + " AdvOnLinkFlag on AdvAutonomousFlag on AdvPreferredLifetime " + allocation->preferred_lifetime + " AdvValidLifetime " + allocation->valid_lifetime + "\n";
-   ncs += "\nif " + config->downstream_interface + " AdvSendAdvertisements on\n";
 
+   // by default, rtadvd configurations enable both Autonomous address-configuration 
+   // and On-link bits, so we don't need to explicitly specify them.
+   string ncs = sprintf("\n%s:\n    addr=\"%s\":prefixlen#%d:vltime#%d:pltime#%d:\n", 
+                        config->downstream_interface, allocation->address, allocation->prefix, 
+                        allocation->valid_lifetime, allocation->preferred_lifetime);
 
 werror("new conf: %O\n", ncs);
    if(ncs != cs) {
      conf = remove_command_segment(conf);
      conf += (preamble + ncs + postamble);
      werror("conf file: %O\n", conf);
-     Stdio.write_file(ndpdconffile, conf);
-   //  Process.popen("/usr/sbin/svcadm restart ndp");
+     Stdio.write_file(conffile, conf);
+     Process.popen("/bin/launchctl kickstart -k " + get_config_value("advertisement_service_name", service));
   }
 }
 
 void prefix_abandoned(IA_PDOption allocation) {
-  string conf = Stdio.read_file(ndpdconffile);
+  string conf = Stdio.read_file(conffile);
   conf = remove_command_segment(conf);
   werror("conf file: %O\n", conf);
-     Stdio.write_file(ndpdconffile, conf);
-   //  Process.popen("/usr/sbin/svcadm restart ndp");
+  Stdio.write_file(conffile, conf);
+  Process.popen("/bin/launchctl kickstart -k " + get_config_value("advertisement_service_name", service));
 }
 
 

          
M MODULE/SystemTypes.pmod/SmartOS.pike +11 -26
@@ 2,10 2,8 @@ import Protocols.DHCPv6;
 
 inherit .Generic;
 
-string preamble = "\n#\n# BEGIN DHCPv6_PD Managed segment\n#\n";
-string postamble = "\n#\n# END DHCPv6_PD Managed segment\n#\n";
-
-string ndpdconffile = "/etc/inet/ndpd.conf";
+string service = "ndp";
+string conffile = "/etc/inet/ndpd.conf";
 
 string get_identifier() {
 //  if(file_stat("/etc/dhcp/duid"))

          
@@ 14,45 12,32 @@ string get_identifier() {
     return Standards.JSON.decode(Process.popen("sysinfo"))->UUID;
 }
 
-string get_command_segment(string conf) {
-  string seg;
-  sscanf(conf, "%*s" + preamble + "%s" + postamble + "%*s", seg);
-  return seg || "";
-}
-
-string remove_command_segment(string conf) {
-  string pre, post;
-  sscanf(conf, "%s" + preamble + "%*s" + postamble + "%s", pre, post);
-  return (pre||"") + (post||"");
-}
-
 void prefix_acquired(IA_PDOption allocation, int has_changed, IA_PDOption old_allocation) {
 werror("prefix_acquired(%O, %O, %O)\n", allocation, has_changed, old_allocation);
 
 // TODO we need to come up with a better mechanism for writing configuration.
-   string conf = Stdio.read_file(ndpdconffile) || "";
+   string conf = Stdio.read_file(conffile) || "";
    string cs = get_command_segment(conf);
 werror("Old conf: %O\n", cs);
-   string ncs="\nprefix " + allocation->address + "/" + allocation->prefix + " " + config->downstream_interface + " AdvOnLinkFlag on AdvAutonomousFlag on AdvPreferredLifetime " + allocation->preferred_lifetime + " AdvValidLifetime " + allocation->valid_lifetime + "\n";
+   string ncs="\nprefix " + allocation->address + "/" + allocation->prefix + " " + config->downstream_interface + 
+     " AdvOnLinkFlag on AdvAutonomousFlag on AdvPreferredLifetime " + allocation->preferred_lifetime + 
+     " AdvValidLifetime " + allocation->valid_lifetime + "\n";
    ncs += "\nif " + config->downstream_interface + " AdvSendAdvertisements on\n";
 
-
 werror("new conf: %O\n", ncs);
    if(ncs != cs) {
      conf = remove_command_segment(conf);
      conf += (preamble + ncs + postamble);
      werror("conf file: %O\n", conf);
-     Stdio.write_file(ndpdconffile, conf);
-     Process.popen("/usr/sbin/svcadm restart ndp");
+     Stdio.write_file(conffile, conf);
+     Process.popen("/usr/sbin/svcadm restart " + get_config_value("advertisement_service_name", service));
   }
 }
 
 void prefix_abandoned(IA_PDOption allocation) {
-  string conf = Stdio.read_file(ndpdconffile);
+  string conf = Stdio.read_file(conffile);
   conf = remove_command_segment(conf);
   werror("conf file: %O\n", conf);
-     Stdio.write_file(ndpdconffile, conf);
-     Process.popen("/usr/sbin/svcadm restart ndp");
+     Stdio.write_file(conffile, conf);
+     Process.popen("/usr/sbin/svcadm restart " + get_config_value("advertisement_service_name", service));
 }
-
-