int afp_volopen_reply(struct afp_server *server, char * buf, unsigned int size, void *other) { struct { struct dsi_header header __attribute__((__packed__)); uint16_t bitmap; } __attribute__((__packed__)) * afp_volopen_reply_packet = (void *) buf; unsigned short bitmap; struct afp_volume **v_p = (void *) other; struct afp_volume * volume=*v_p; if (size < sizeof (*afp_volopen_reply_packet)) return -1; bitmap=ntohs(afp_volopen_reply_packet->bitmap); if (parse_volbitmap_reply(server,volume, bitmap, buf+sizeof(*afp_volopen_reply_packet), size-sizeof(*afp_volopen_reply_packet))!=0) return -1; if (volume->attributes & kSupportsUTF8Names) { convert_utf8dec_to_utf8pre(volume->volume_name, strlen(volume->volume_name), volume->volume_name_printable, AFP_VOLUME_NAME_UTF8_LEN); } else { memcpy(volume->volume_name_printable, volume->volume_name,AFP_VOLUME_NAME_LEN); } return 0; }
void dsi_getstatus_reply(struct afp_server * server) { /* Todo: check for buffer overruns */ char * data, *p, *p2; int len; uint16_t * offset; /* This is the fixed portion */ struct dsi_getstatus_header { struct dsi_header dsi __attribute__((__packed__)); uint16_t machine_offset; uint16_t version_offset; uint16_t uams_offset; uint16_t icon_offset; uint16_t flags ; } __attribute__((__packed__)) * reply1 = (void *) server->incoming_buffer; struct reply2 { uint16_t signature_offset; uint16_t networkaddress_offset; uint16_t directoryservices_offset; uint16_t utf8servername_offset; } __attribute__((__packed__)) * reply2; if (server->data_read < (sizeof(*reply1) + sizeof(*reply2))) { log_for_client(NULL,AFPFSD,LOG_ERR, "Got incomplete data for getstatus\n"); return ; } data = (char * ) server->incoming_buffer + sizeof(struct dsi_header); /* First, get the fixed portion */ p=data + ntohs(reply1->machine_offset); copy_from_pascal(server->machine_type,p,AFP_MACHINETYPE_LEN); p=data + ntohs(reply1->version_offset); dsi_parse_versions(server, p); p=data + ntohs(reply1->uams_offset); dsi_parse_uams(server, p); if (ntohs(reply1->icon_offset)>0) { /* The icon and mask are optional */ p=data + ntohs(reply1->icon_offset); memcpy(server->icon,p,256); } server->flags=ntohs(reply1->flags); p=(void *)((unsigned int) server->incoming_buffer + sizeof(*reply1)); p+=copy_from_pascal(server->server_name,p,AFP_SERVER_NAME_LEN)+1; /* Now work our way through the variable bits */ /* First, make sure we're on an even boundary */ if (((uint64_t) p) & 0x1) p++; /* Get the signature */ offset = (uint16_t *) p; memcpy(server->signature, ((void *) data)+ntohs(*offset), AFP_SIGNATURE_LEN); p+=2; /* The network addresses */ if (server->flags & kSupportsTCP) { offset = (uint16_t *) p; /* We don't actually do anything with the network addresses, * but if we did, it'd go here */ p+=2; } /* The directory names */ if (server->flags & kSupportsDirServices) { offset = (uint16_t *) p; /* We don't actually do anything with the directory names, * but if we did, it'd go here */ p+=2; } if (server->flags & kSupportsUTF8SrvrName) { /* And now the UTF8 server name */ offset = (uint16_t *) p; p2=((void *) data)+ntohs(*offset); /* Skip the hint character */ p2+=1; len=copy_from_pascal(server->server_name_utf8,p2, AFP_SERVER_NAME_UTF8_LEN); /* This is a workaround. There's a bug in netatalk that in some * circumstances puts the UTF8 servername off by one character */ if (len==0) { p2++; len=copy_from_pascal(server->server_name_utf8,p2, AFP_SERVER_NAME_UTF8_LEN); } convert_utf8dec_to_utf8pre(server->server_name_utf8, strlen(server->server_name_utf8), server->server_name_printable, AFP_SERVER_NAME_UTF8_LEN); } else { /* We don't have a UTF8 servername, so let's make one */ iconv_t cd; size_t inbytesleft = strlen(server->server_name); size_t outbytesleft = AFP_SERVER_NAME_UTF8_LEN; char * inbuf = server->server_name; char * outbuf = server->server_name_printable; if ((cd = iconv_open("MACINTOSH","UTF-8")) == (iconv_t) -1) return; iconv(cd,&inbuf,&inbytesleft, &outbuf, &outbytesleft); iconv_close(cd); } }