+static size_t status_directorynames(char *data, int *diroffset,
+ const DSI *dsi _U_,
+ const struct afp_options *options)
+{
+ char *begin = data;
+ u_int16_t offset;
+ memcpy(&offset, data + *diroffset, sizeof(offset));
+ offset = ntohs(offset);
+ data += offset;
+
+ /* I can not find documentation of any other purpose for the
+ * DirectoryNames field.
+ */
+ /*
+ * Try to synthesize a principal:
+ * service '/' fqdn '@' realm
+ */
+ if (options->k5service && options->k5realm && options->fqdn) {
+ /* should k5princ be utf8 encoded? */
+ size_t len;
+ char *p = strchr( options->fqdn, ':' );
+ if (p)
+ *p = '\0';
+ len = strlen( options->k5service )
+ + strlen( options->fqdn )
+ + strlen( options->k5realm );
+ len+=2; /* '/' and '@' */
+ if ( len > 255 || len+2 > maxstatuslen - offset) {
+ *data++ = 0;
+ LOG ( log_error, logtype_afpd, "status: could not set directory service list, no more room");
+ }
+ else {
+ *data++ = 1; /* DirectoryNamesCount */
+ *data++ = len;
+ snprintf( data, len + 1, "%s/%s@%s", options->k5service,
+ options->fqdn, options->k5realm );
+ data += len;
+ if (p)
+ *p = ':';
+ }
+ } else {
+ *data++ = 0;
+ }
+
+ /* Calculate and store offset for UTF8ServerName */
+ *diroffset += sizeof(u_int16_t);
+ offset = htons(data - begin);
+ memcpy(begin + *diroffset, &offset, sizeof(u_int16_t));
+
+ /* return length of buffer */
+ return (data - begin);
+}
+
+static size_t status_utf8servername(char *data, int *nameoffset,
+ const DSI *dsi _U_,
+ const struct afp_options *options)
+{
+ char *Obj, *Type, *Zone;
+ u_int16_t namelen;
+ size_t len;
+ char *begin = data;
+ u_int16_t offset, status;
+
+ memcpy(&offset, data + *nameoffset, sizeof(offset));
+ offset = ntohs(offset);
+ data += offset;
+
+ /* FIXME:
+ * What is the valid character range for an nbpname?
+ *
+ * Apple's server likes to use the non-qualified hostname
+ * This obviously won't work very well if multiple servers are running
+ * on the box.
+ */
+
+ /* extract the obj part of the server */
+ Obj = (char *) (options->server ? options->server : options->hostname);
+ nbp_name(options->server ? options->server : options->hostname, &Obj, &Type, &Zone);
+
+ if ((size_t) -1 == (len = convert_string (
+ options->unixcharset, CH_UTF8_MAC,
+ Obj, -1, data+sizeof(namelen), maxstatuslen-offset )) ) {
+ LOG ( log_error, logtype_afpd, "Could not set utf8 servername");
+
+ /* set offset to 0 */
+ memset(begin + *nameoffset, 0, sizeof(offset));
+ data = begin + offset;
+ }
+ else {
+ namelen = htons(len);
+ memcpy( data, &namelen, sizeof(namelen));
+ data += sizeof(namelen);
+ data += len;
+ offset = htons(offset);
+ memcpy(begin + *nameoffset, &offset, sizeof(u_int16_t));
+
+ /* Now set the flag ... */
+ memcpy(&status, begin + AFPSTATUS_FLAGOFF, sizeof(status));
+ status = ntohs(status);
+ status |= AFPSRVRINFO_SRVUTF8;
+ status = htons(status);
+ memcpy(begin + AFPSTATUS_FLAGOFF, &status, sizeof(status));
+ }
+
+ /* return length of buffer */
+ return (data - begin);
+
+}
+