*curr = new;
}
}
+
+
+//brcm begin
+void viInfoFree(pVI_OPTION_INFO pInfo)
+{
+ if (pInfo) {
+ free(pInfo->oui);
+ free(pInfo->serialNumber);
+ free(pInfo->productClass);
+ free(pInfo);
+ }
+}
+
+void addViToList(pVI_OPTION_INFO pNew) {
+ pVI_OPTION_INFO pPtr= NULL;
+
+ /* if VI exists already, don't add, just update the info */
+ if (viList->count > 0) {
+ pPtr = viList->pHead;
+ while (pPtr) {
+ if (pPtr->ipAddr == pNew->ipAddr) {
+ /* found it, just copy the info over */
+ memcpy(pPtr,pNew,sizeof(VI_OPTION_INFO));
+ viInfoFree(pNew);
+ return;
+ }
+ pPtr = pPtr->next;
+ } /* while */
+ } /* list has something */
+
+ if (viList->pHead == NULL) {
+ viList->pHead = pNew;
+ viList->pTail = pNew;
+ }
+ else {
+ viList->pTail->next = pNew;
+ viList->pTail = pNew;
+ }
+ viList->count++;
+}
+
+void viListFree(void)
+{
+ pVI_OPTION_INFO pInfo;
+
+ while (viList->pHead) {
+ pInfo = viList->pHead;
+ viList->pHead = viList->pHead->next;
+ free(pInfo->oui);
+ free(pInfo->serialNumber);
+ free(pInfo->productClass);
+ free(pInfo);
+ }
+ viList->count = 0;
+}
+
+
+/* this function generates VI info based on TR111 part I.
+ If -1 is return, there is no VI info found. Otherwise, 0 is returned.
+ Type specifies gateway vendor info or device vendor info.
+ VIinfo is where the option string is stored */
+int createVIoption(int type, char *VIinfo)
+{
+ FILE* fs;
+ char optionData[VENDOR_IDENTIFYING_INFO_LEN], *dataPtr;
+ int len, totalLen = 0;
+ char line[VENDOR_IDENTIFYING_INFO_LEN];
+ char oui[6];
+ char serialNum[64];
+ char productClass[64];
+
+ fs = fopen("/var/fyi/sys/info", "r");
+ if (fs == NULL) {
+ return (-1);
+ }
+ fgets(line, VENDOR_IDENTIFYING_INFO_LEN, fs);
+ sscanf(line, "OUI %s\n", oui);
+ fgets(line, VENDOR_IDENTIFYING_INFO_LEN, fs);
+ sscanf(line, "SerialNumber %s\n", serialNum);
+ fgets(line, VENDOR_IDENTIFYING_INFO_LEN, fs);
+ sscanf(line, "ProductClass %s\n", productClass);
+ fclose(fs);
+
+ optionData[VENDOR_OPTION_CODE_OFFSET] = (char)VENDOR_IDENTIFYING_OPTION_CODE;
+ *(unsigned int*)(optionData+VENDOR_OPTION_ENTERPRISE_OFFSET) = (unsigned int)VENDOR_BRCM_ENTERPRISE_NUMBER;
+ dataPtr = optionData + VENDOR_OPTION_DATA_OFFSET;
+ totalLen = VENDOR_ENTERPRISE_LEN;
+ /* read system information and add it to option data */
+ /* OUI */
+ if (type == VENDOR_IDENTIFYING_FOR_DEVICE)
+ *dataPtr++ = (char)VENDOR_DEVICE_OUI_SUBCODE;
+ else
+ *dataPtr++ = (char)VENDOR_GATEWAY_OUI_SUBCODE;
+ len = strlen(oui);
+ *dataPtr++ = len;
+ strncpy(dataPtr,oui,len);
+ dataPtr += len;
+ totalLen += (len + VENDOR_SUBCODE_AND_LEN_BYTES);
+
+ /* Serial Number */
+ if (type == VENDOR_IDENTIFYING_FOR_DEVICE)
+ *dataPtr++ = (char)VENDOR_DEVICE_SERIAL_NUMBER_SUBCODE;
+ else
+ *dataPtr++ = (char)VENDOR_GATEWAY_SERIAL_NUMBER_SUBCODE;
+ len = strlen(serialNum);
+ *dataPtr++ = len;
+ strncpy(dataPtr,(const char*)serialNum,len);
+ dataPtr += len;
+ totalLen += (len + VENDOR_SUBCODE_AND_LEN_BYTES);
+
+ /* Product Class */
+ if (type == VENDOR_IDENTIFYING_FOR_DEVICE)
+ *dataPtr++ = VENDOR_DEVICE_PRODUCT_CLASS_SUBCODE;
+ else
+ *dataPtr++ = VENDOR_GATEWAY_PRODUCT_CLASS_SUBCODE;
+ len = strlen(productClass);
+ *dataPtr++ = len;
+ strncpy(dataPtr,(const char*)productClass,len);
+ dataPtr += len;
+ totalLen += (len + VENDOR_SUBCODE_AND_LEN_BYTES);
+
+ optionData[VENDOR_OPTION_LEN_OFFSET] = totalLen;
+
+ /* also copy the option code and option len which is not counted in total len */
+ memcpy((void*)VIinfo,(void*)optionData,(totalLen+VENDOR_OPTION_DATA_OFFSET));
+
+ return 0;
+}
+/* udp_send and readIp from voice */
+static int readIp(const char* ip)
+{
+ int n = 0;
+ int res = 0;
+
+ while (n < 4 && *ip)
+ {
+ if (isdigit(*ip))
+ {
+ res = (res << 8) | atoi(ip);
+ n++;
+ while (isdigit(*ip))
+ {
+ ip++;
+ }
+ }
+ else
+ {
+ ip++;
+ }
+ }
+ return res;
+}
+
+static int notifyApp(short port, void *data, int len)
+{
+ int sockfd;
+ struct sockaddr_in serv_addr;
+ struct sockaddr_in cli_addr;
+
+ /* fill in server address */
+ memset(&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_addr.s_addr = readIp("127.0.0.1");
+ serv_addr.sin_port = htons(port);
+
+ /* open udp socket */
+ if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ {
+ printf("WT-104: Could not open socket for send\n");
+ return -1; /* could not open socket */
+ }
+
+ /* bind any local address for us */
+ memset(&cli_addr, 0, sizeof(cli_addr));
+ cli_addr.sin_family = AF_INET;
+ cli_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ cli_addr.sin_port = htons(0);
+
+ if (bind(sockfd, (struct sockaddr *) &cli_addr, sizeof(cli_addr)) < 0)
+ {
+ printf("dhcpd: Could not bind client socket\n");
+ return -2; /* could not bind client socket */
+ }
+
+ /* send the data */
+ if (sendto(sockfd, data, len, 0, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) != len)
+ {
+ printf( "dhcpd: Could not sendto\n");
+ return -3; /* could not sendto */
+ }
+ close(sockfd);
+ return 0;
+}
+
+/* this function parses received VI info, and save it.
+ If -1 is return, there is no VI info found; invalid option. Otherwise, 0 is returned.
+ *option is the received option string to parse; it points to optionData.
+ ipAddr is the device's offered address or device's ip address */
+int saveVIoption(char *option, u_int32_t ipAddr)
+{
+ char *optionPtr;
+
+ int maxSubcode = 3;
+ int subcodeParsed = 0;
+ int subcode, sublen;
+ pVI_OPTION_INFO pInfo = NULL;
+ int ret = 0;
+ int msg = 0;
+
+ if (option == NULL) {
+ DEBUG(LOG_ERR, "saveVIoption(): option is NULL.");
+ return -1;
+ }
+
+ optionPtr = option;
+ pInfo = malloc(sizeof(VI_OPTION_INFO));
+ memset(pInfo,0,sizeof(VI_OPTION_INFO));
+ pInfo->enterprise = *(unsigned int*)(optionPtr);
+ pInfo->ipAddr = ipAddr;
+ optionPtr += VENDOR_ENTERPRISE_LEN;
+
+ while (subcodeParsed < maxSubcode) {
+ /* subcode, len, data */
+ subcode = *optionPtr++;
+ sublen = *optionPtr++;
+ subcodeParsed++;
+ switch (subcode)
+ {
+ case VENDOR_DEVICE_OUI_SUBCODE:
+ case VENDOR_GATEWAY_OUI_SUBCODE:
+ if (sublen <= VENDOR_GATEWAY_OUI_MAX_LEN) {
+ if ((pInfo->oui = malloc(sublen+1)) != NULL) {
+ memcpy(pInfo->oui,optionPtr,sublen);
+ pInfo->oui[sublen] = '\0';
+ }
+ else
+ goto viError;
+ }
+ else {
+ DEBUG(LOG_ERR, "saveVIoption(): subcode OUI, OUI len %d is too long.",sublen);
+ goto viError;
+ }
+ break;
+ case VENDOR_DEVICE_SERIAL_NUMBER_SUBCODE:
+ case VENDOR_GATEWAY_SERIAL_NUMBER_SUBCODE:
+ if (sublen <= VENDOR_GATEWAY_SERIAL_NUMBER_MAX_LEN) {
+ if ((pInfo->serialNumber = malloc(sublen+1)) != NULL) {
+ memcpy(pInfo->serialNumber,optionPtr,sublen);
+ pInfo->serialNumber[sublen] = '\0';
+ }
+ else
+ goto viError;
+ }
+ else {
+ DEBUG(LOG_ERR, "saveVIoption(): subcode SerialNumber, Serial Number len %d is too long.",sublen);
+ goto viError;
+ }
+ break;
+ case VENDOR_DEVICE_PRODUCT_CLASS_SUBCODE:
+ case VENDOR_GATEWAY_PRODUCT_CLASS_SUBCODE:
+ if (sublen <= VENDOR_GATEWAY_PRODUCT_CLASS_MAX_LEN) {
+ if ((pInfo->productClass = malloc(sublen+1)) != NULL) {
+ memcpy(pInfo->productClass,optionPtr,sublen);
+ pInfo->productClass[sublen] = '\0';
+ }
+ else
+ goto viError;
+ }
+ else {
+ DEBUG(LOG_ERR, "saveVIoption(): subcode ProductClass, Class len %d is too long.",sublen);
+ goto viError;
+ }
+ break;
+ default:
+ DEBUG(LOG_ERR, "saveVIoption(): subcode %d, not supported.",subcode);
+ goto viError;
+ }
+ optionPtr += sublen;
+ /* add info to the manageable device link list */
+ } /* while subcodeParsed < maxSubcode */
+ addViToList(pInfo);
+ notifyApp(30006,(void*)&msg,sizeof(msg));
+
+ return ret;
+
+ viError:
+ ret = -1;
+ if (pInfo) {
+ if (pInfo->oui)
+ free(pInfo->oui);
+ if (pInfo->serialNumber)
+ free(pInfo->serialNumber);
+ if (pInfo->productClass)
+ free(pInfo->productClass);
+ free(pInfo);
+ }
+ return ret;
+}
+
+
+//brcm end