#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/file.h>
+#include <sys/kauth.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
-#include <net/etherdefs.h>
-#include <net/tokendefs.h>
#include <net/dlil.h>
#include <netat/appletalk.h>
#include <netat/routing_tables.h>
#include <netat/debug.h>
-extern int at_ioctl(struct atpcb *, u_long, caddr_t);
+#include <sys/kern_event.h>
+
+extern int at_ioctl(struct atpcb *, u_long, caddr_t, int fromKernel);
extern int routerStart(at_kern_err_t *);
extern void elap_offline(at_ifaddr_t *);
extern at_ifaddr_t *find_ifID(char *);
{0xC0, 0x00, 0x40, 0x00, 0x00, 0x00}};
/* called only in router mode */
-static int set_zones(ifz)
- zone_usage_t *ifz;
+static int set_zones(zone_usage_t *ifz)
/* 1. adds zone to table
2. looks up each route entry from zone list
* ifp is 0 if not an interface-specific ioctl.
*/
-int at_control(so, cmd, data, ifp)
+int
+at_control(so, cmd, data, ifp)
struct socket *so;
u_long cmd;
caddr_t data;
struct ifaddr *ifa;
struct sockaddr_dl *sdl;
- if (cmd == 0x2000ff99) {
+ if ((cmd & 0xffff) == 0xff99) {
+ u_long fixed_command;
/* *** this is a temporary hack to get at_send_to_dev() to
work with BSD-style sockets instead of the special purpose
system calls, ATsocket() and ATioctl().
*** */
- if ((error = at_ioctl((struct atpcb *)so->so_pcb, cmd, data))) {
+ fixed_command = _IOW(0, 0xff99, user_addr_t);
+ if ((error = at_ioctl((struct atpcb *)so->so_pcb, fixed_command, data, 0))) {
if (((struct atpcb *)so->so_pcb)->proto != ATPROTO_LAP) {
((struct atpcb *)so->so_pcb)->proto = ATPROTO_LAP;
- error = at_ioctl((struct atpcb *)so->so_pcb, cmd, data);
+ error = at_ioctl((struct atpcb *)so->so_pcb, fixed_command, data , 0);
}
}
return(error);
at_def_zone_t *defzonep = (at_def_zone_t *)data;
/* check for root access */
- if (error = suser(p->p_ucred, &p->p_acflag))
+ if (error = suser(kauth_cred_get(), 0))
return(EACCES);
ifID = 0;
/* check the zone name */
if (MULTIPORT_MODE) {
short zno;
- char ifs_in_zone[IF_TOTAL_MAX];
+ at_ifnames_t ifs_in_zone;
if (!(zno = zt_find_zname(&defzonep->zonename)))
return(EINVAL);
- getIfUsage(zno-1, ifs_in_zone);
- if (!ifs_in_zone[ifID->ifPort])
+ getIfUsage(zno-1, &ifs_in_zone);
+ if (!ifs_in_zone.at_if[ifID->ifPort])
return(EINVAL);
ifID->ifDefZone = zno+1;
} else {
}
ifID->ifZoneName = defzonep->zonename;
(void)regDefaultZone(ifID);
+
+ /* AppleTalk zone was changed. Send event with zone info. */
+ atalk_post_msg(ifID->aa_ifp, KEV_ATALK_ZONEUPDATED, 0, &(ifID->ifZoneName));
+
return(0);
}
} else
{
at_nbp_reg_t *nbpP = (at_nbp_reg_t *)data;
nve_entry_t nve;
- int error;
+ int error2;
if (!(at_state.flags & AT_ST_STARTED) || !ifID_home)
return(ENOTREADY);
this zone */
int finished = FALSE;
int zno;
- char ifs_in_zone[IF_TOTAL_MAX];
+ at_ifnames_t ifs_in_zone;
if (!(zno = zt_find_zname(&nve.zone))) {
return(EINVAL);
}
- getIfUsage(zno-1, ifs_in_zone);
+ getIfUsage(zno-1, &ifs_in_zone);
TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
- if (!ifs_in_zone[ifID->ifPort])
+ if (!ifs_in_zone.at_if[ifID->ifPort])
/* zone doesn't match */
continue;
- else
+ else {
finished = TRUE;
+ break;
+ }
}
if (!finished)
return(EINVAL);
/* Normal case; no tuple found for this name, so insert
* this tuple in the registry and return ok response.
*/
- ATDISABLE(nve_lock, NVE_LOCK);
- if ((error = nbp_new_nve_entry(&nve, ifID)) == 0) {
+ if ((error2 = nbp_new_nve_entry(&nve, ifID)) == 0) {
nbpP->addr.net = ifID->ifThisNode.s_net;
nbpP->addr.node = ifID->ifThisNode.s_node;
nbpP->unique_nbp_id = nve.unique_nbp_id;
}
- ATENABLE(nve_lock, NVE_LOCK);
- return(error);
+ return(error2);
break;
}
/* delete by id */
if (nbpP->unique_nbp_id) {
- ATDISABLE(nve_lock, NVE_LOCK);
TAILQ_FOREACH(nve_entry, &name_registry, nve_link) {
if (nve_entry->unique_nbp_id == nbpP->unique_nbp_id) {
/* Found a match! */
nbp_delete_entry(nve_entry);
- ATENABLE(nve_lock, NVE_LOCK);
return(0);
}
}
- ATENABLE(nve_lock, NVE_LOCK);
return(EADDRNOTAVAIL);
}
if ((nve_entry = nbp_find_nve(&nve)) == NULL)
continue;
- ATDISABLE(nve_lock, NVE_LOCK);
nbp_delete_entry(nve_entry);
- ATENABLE(nve_lock, NVE_LOCK);
found = TRUE;
}
if (found)
/* Normal case; tuple found for this name, so delete
* the entry from the registry and return ok response.
*/
- ATDISABLE(nve_lock, NVE_LOCK);
nbp_delete_entry(nve_entry);
- ATENABLE(nve_lock, NVE_LOCK);
return(0);
break;
at_router_params_t *rt = (at_router_params_t *)data;
/* check for root access */
- if (error = suser(p->p_ucred, &p->p_acflag))
+ if (error = suser(kauth_cred_get(), 0))
return(EACCES);
/* when in routing/multihome mode the AIOCSETROUTER IOCTL
at_kern_err_t *keP = (at_kern_err_t *)data;
/* check for root access */
- if (suser(p->p_ucred, &p->p_acflag))
+ if (suser(kauth_cred_get(), 0))
return(EACCES);
if (!(at_state.flags & AT_ST_STARTED))
break;
}
case AIOCSTOPATALK:
- {
- int *count_only = (int *)data,
+ {
+ int *count_only = (int *)data,
ret;
/* check for root access */
- if (error = suser(p->p_ucred, &p->p_acflag))
+ if (error = suser(kauth_cred_get(), 0))
return(EACCES);
ret = ddp_shutdown(*count_only);
- if (*count_only) {
+
+ if (*count_only != 0)
+ {
*count_only = ret;
return(0);
- } else
- return((ret == 0)? 0 : EBUSY);
+ }
+ else
+ {
+ if (ret == 0)
+ {
+ /* AppleTalk was successfully shut down. Send event. */
+ atalk_post_msg(0, KEV_ATALK_DISABLED, 0, 0);
+ return 0;
+ }
+ else
+ return EBUSY;
+ }
+
break;
- }
+ }
case SIOCSIFADDR:
/* check for root access */
- if (error = suser(p->p_ucred, &p->p_acflag))
+ if (error = suser(kauth_cred_get(), 0))
error = EACCES;
else if (ifID)
error = EEXIST;
else {
int s;
if (xpatcnt == 0) {
- at_state.flags |= AT_ST_STARTED;
+ at_state.flags |= AT_ST_STARTING;
ddp_brt_init();
}
ifID->aa_ifp = ifp;
ifa = &ifID->aa_ifa;
+ ifnet_lock_exclusive(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
(sdl->sdl_family == AF_LINK)) {
ifID->ifNodeAddress.sat_family = AF_APPLETALK;
/* the address itself will be filled in when ifThisNode
is set */
- s = splnet();
- TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
- splx(s);
+ if_attach_ifa(ifp, ifa);
+ ifnet_lock_done(ifp);
switch (ifp->if_type) {
case IFT_ETHER:
- ether_attach_at(ifp, &ifID->at_dl_tag,
- &ifID->aarp_dl_tag);
+ case IFT_L2VLAN:
+ case IFT_IEEE8023ADLAG: /* bonded ethernet */
+ ether_attach_at(ifp);
error = 0;
ifID->cable_multicast_addr = etalk_multicast_addr;
/* complete the initialization started in SIOCSIFADDR */
case AIOCSIFADDR:
- {
+ {
at_if_cfg_t *cfgp = (at_if_cfg_t *)data;
- if (!(at_state.flags & AT_ST_STARTED))
+ if (!(at_state.flags & AT_ST_STARTING))
return(ENOTREADY);
if (!(ifID = find_ifID(cfgp->ifr_name)))
return(EINVAL);
-
+
return(lap_online(ifID, cfgp));
break;
- }
+ }
#ifdef NOT_YET
/* *** this can't be added until AT can handle dynamic addition and
deletion of interfaces *** */
case SIOCDIFADDR:
/* check for root access */
- if (error = suser(p->p_ucred, &p->p_acflag))
+ if (error = suser(kauth_cred_get(), 0))
error = EACCES;
else if (!ifID)
error = EINVAL;
#endif
case SIOCSETOT: {
- int s;
struct atpcb *at_pcb, *clonedat_pcb;
int cloned_fd = *(int *)data;
- s = splnet(); /* XXX */
at_pcb = sotoatpcb(so);
/* let's make sure it's either -1 or a valid file descriptor */
if (cloned_fd != -1) {
struct socket *cloned_so;
- struct file *cloned_fp;
- error = getsock(p->p_fd, cloned_fd, &cloned_fp);
- if (error){
- splx(s); /* XXX */
+ error = file_socket(cloned_fd, &cloned_so);
+ if (error)
break;
- }
- cloned_so = (struct socket *)cloned_fp->f_data;
clonedat_pcb = sotoatpcb(cloned_so);
} else {
clonedat_pcb = NULL;
} else {
at_pcb->ddp_flags = clonedat_pcb->ddp_flags;
}
- splx(s); /* XXX */
+ file_drop(cloned_fd);
break;
}
return(error);
}
+
+/* From dlil_post_msg() */
+void atalk_post_msg(struct ifnet *ifp, u_long event_code, struct at_addr *address, at_nvestr_t *zone)
+{
+ struct kev_atalk_data at_event_data;
+ struct kev_msg ev_msg;
+
+ ev_msg.vendor_code = KEV_VENDOR_APPLE;
+ ev_msg.kev_class = KEV_NETWORK_CLASS;
+ ev_msg.kev_subclass = KEV_ATALK_SUBCLASS;
+ ev_msg.event_code = event_code;
+
+ bzero(&at_event_data, sizeof(struct kev_atalk_data));
+
+ if (ifp != 0) {
+ strncpy(&at_event_data.link_data.if_name[0], ifp->if_name, IFNAMSIZ);
+ at_event_data.link_data.if_family = ifp->if_family;
+ at_event_data.link_data.if_unit = (unsigned long) ifp->if_unit;
+ }
+
+ if (address != 0) {
+ at_event_data.node_data.address = *address;
+ }
+ else if (zone != 0) {
+ at_event_data.node_data.zone = *zone;
+ }
+
+ ev_msg.dv[0].data_length = sizeof(struct kev_atalk_data);
+ ev_msg.dv[0].data_ptr = &at_event_data;
+ ev_msg.dv[1].data_length = 0;
+
+ kev_post_msg(&ev_msg);
+}