1 /****************************************************************************
2 Copyright (c) 2012, Intel Corporation
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 1. Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
15 3. Neither the name of the Intel Corporation nor the names of its
16 contributors may be used to endorse or promote products derived from
17 this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 POSSIBILITY OF SUCH DAMAGE.
31 ******************************************************************************/
33 * MVRP protocol (part of 802.1Q-2011)
45 int mvrp_send_notifications(struct mvrp_attribute *attrib, int notify);
48 unsigned char MVRP_CUSTOMER_BRIDGE_ADDR[] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x21 }; /* 81-00 */
49 unsigned char MVRP_PROVIDER_BRIDGE_ADDR[] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x0D }; /* 88-A8 */
51 extern unsigned char STATION_ADDR[];
53 /* global variables */
55 struct mvrp_database *MVRP_db;
59 struct mvrp_attribute *mvrp_lookup(struct mvrp_attribute *rattrib)
61 struct mvrp_attribute *attrib;
63 attrib = MVRP_db->attrib_list;
64 while (NULL != attrib) {
65 if (attrib->attribute == rattrib->attribute)
67 attrib = attrib->next;
72 int mvrp_add(struct mvrp_attribute *rattrib)
74 struct mvrp_attribute *attrib;
75 struct mvrp_attribute *attrib_tail;
77 /* XXX do a lookup first to guarantee uniqueness? */
79 attrib_tail = attrib = MVRP_db->attrib_list;
81 while (NULL != attrib) {
82 if (attrib->attribute < rattrib->attribute) {
83 /* possible tail insertion ... */
84 if (NULL != attrib->next) {
85 attrib = attrib->next;
88 rattrib->next = attrib->next;
89 rattrib->prev = attrib;
90 attrib->next = rattrib;
94 /* head insertion ... */
95 rattrib->next = attrib;
96 rattrib->prev = attrib->prev;
97 attrib->prev = rattrib;
98 if (NULL != rattrib->prev)
99 rattrib->prev->next = rattrib;
101 MVRP_db->attrib_list = rattrib;
105 attrib_tail = attrib;
106 attrib = attrib->next;
109 /* if we are here we didn't need to stitch in a a sorted entry
110 * so append it onto the tail (if it exists)
113 if (NULL == attrib_tail) {
114 rattrib->next = NULL;
115 rattrib->prev = NULL;
116 MVRP_db->attrib_list = rattrib;
118 rattrib->next = NULL;
119 rattrib->prev = attrib_tail;
120 attrib_tail->next = rattrib;
126 int mvrp_merge(struct mvrp_attribute *rattrib)
128 struct mvrp_attribute *attrib;
130 attrib = mvrp_lookup(rattrib);
133 return -1; /* shouldn't happen */
135 /* primarily we update the last mac address state for diagnostics */
136 memcpy(attrib->registrar.macaddr, rattrib->registrar.macaddr, 6);
140 int mvrp_event(int event, struct mvrp_attribute *rattrib)
142 struct mvrp_attribute *attrib;
146 case MRP_EVENT_LVATIMER:
147 mrp_jointimer_stop(&(MVRP_db->mrp_db));
149 attrib = MVRP_db->attrib_list;
151 while (NULL != attrib) {
152 mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_TXLA);
153 mrp_registrar_fsm(&(attrib->registrar),
154 &(MVRP_db->mrp_db), MRP_EVENT_TXLA);
155 attrib = attrib->next;
158 mrp_lvatimer_fsm(&(MVRP_db->mrp_db), MRP_EVENT_LVATIMER);
163 mrp_jointimer_stop(&(MVRP_db->mrp_db));
165 attrib = MVRP_db->attrib_list;
167 while (NULL != attrib) {
168 mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_RLA);
169 mrp_registrar_fsm(&(attrib->registrar),
170 &(MVRP_db->mrp_db), MRP_EVENT_RLA);
171 attrib = attrib->next;
174 mrp_lvatimer_fsm(&(MVRP_db->mrp_db), MRP_EVENT_RLA);
178 mrp_jointimer_stop(&(MVRP_db->mrp_db));
179 attrib = MVRP_db->attrib_list;
181 while (NULL != attrib) {
182 mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_TX);
183 attrib = attrib->next;
186 mrp_lvatimer_fsm(&(MVRP_db->mrp_db), MRP_EVENT_TX);
190 case MRP_EVENT_LVTIMER:
191 mrp_lvtimer_stop(&(MVRP_db->mrp_db));
192 attrib = MVRP_db->attrib_list;
194 while (NULL != attrib) {
195 mrp_registrar_fsm(&(attrib->registrar),
199 attrib = attrib->next;
202 case MRP_EVENT_PERIODIC:
203 attrib = MVRP_db->attrib_list;
205 while (NULL != attrib) {
206 mrp_applicant_fsm(&(attrib->applicant),
208 attrib = attrib->next;
214 case MRP_EVENT_RJOININ:
215 case MRP_EVENT_RJOINMT:
220 mrp_jointimer_start(&(MVRP_db->mrp_db));
222 return -1; /* XXX internal fault */
225 attrib = mvrp_lookup(rattrib);
227 if (NULL == attrib) {
235 mrp_applicant_fsm(&(attrib->applicant), event);
236 /* remap local requests into registrar events */
239 mrp_registrar_fsm(&(attrib->registrar),
240 &(MVRP_db->mrp_db), MRP_EVENT_RNEW);
243 if (MRP_IN_STATE == attrib->registrar.mrp_state)
244 mrp_registrar_fsm(&(attrib->registrar),
248 mrp_registrar_fsm(&(attrib->registrar),
253 mrp_registrar_fsm(&(attrib->registrar),
254 &(MVRP_db->mrp_db), MRP_EVENT_RLV);
257 rc = mrp_registrar_fsm(&(attrib->registrar),
258 &(MVRP_db->mrp_db), event);
261 ("MVRP registrar error on attrib->attribute = %d\n",
272 * XXX should honor the MVRP_db->mrp_db.registration and
273 * MVRP_db->mrp_db.participant controls
276 /* generate local notifications */
277 attrib = MVRP_db->attrib_list;
279 while (NULL != attrib) {
280 if (MRP_NOTIFY_NONE != attrib->registrar.notify) {
281 mvrp_send_notifications(attrib,
282 attrib->registrar.notify);
283 attrib->registrar.notify = MRP_NOTIFY_NONE;
285 attrib = attrib->next;
291 struct mvrp_attribute *mvrp_alloc()
293 struct mvrp_attribute *attrib;
295 attrib = malloc(sizeof(struct mvrp_attribute));
299 memset(attrib, 0, sizeof(struct mvrp_attribute));
301 attrib->applicant.mrp_state = MRP_VO_STATE;
302 attrib->applicant.tx = 0;
303 attrib->applicant.sndmsg = MRP_SND_NULL;
304 attrib->applicant.encode = MRP_ENCODE_OPTIONAL;
306 attrib->registrar.mrp_state = MRP_MT_STATE;
307 attrib->registrar.notify = MRP_NOTIFY_NONE;
312 int mvrp_recv_msg(void)
318 mrpdu_message_t *mrpdu_msg;
319 unsigned char *mrpdu_msg_ptr;
320 unsigned char *mrpdu_msg_eof;
321 mrpdu_vectorattrib_t *mrpdu_vectorptr;
323 uint16_t numvalues_processed;
329 uint16_t vid_firstval;
330 struct mvrp_attribute *attrib;
333 bytes = mrpd_recvmsgbuf(mvrp_socket, &msgbuf);
337 if ((unsigned int)bytes < (sizeof(eth_hdr_t) + sizeof(mrpdu_t) +
338 sizeof(mrpdu_message_t)))
341 eth = (eth_hdr_t *) msgbuf;
343 /* note that MVRP frames should always arrive untagged (no vlan) */
344 if (MVRP_ETYPE != ntohs(eth->typelen))
347 /* XXX check dest mac address too? */
349 mrpdu = (mrpdu_t *) (msgbuf + sizeof(struct eth_hdr));
352 * ProtocolVersion handling - a receiver must process received frames with a lesser
353 * protcol version consistent with the older protocol processing requirements (e.g. a V2
354 * agent receives a V1 message, the V1 message shoudl be parsed with V1 rules).
356 * However - if an agent receives a NEWER protocol, the agent shoudl still attempt
357 * to parse the frame. If the agent finds an AttributeType not recognized
358 * the agent discards the current message including any associated trailing vectors
359 * up to the end-mark, and resumes with the next message or until the end of the PDU
362 * If a VectorAttribute is found with an unknown Event for the Type, the specific
363 * VectorAttrute is discarded and processing continues with the next VectorAttribute.
366 if (MVRP_PROT_VER != mrpdu->ProtocolVersion) /* XXX should accept ... */
369 mrpdu_msg_ptr = (unsigned char *)MRPD_GET_MRPDU_MESSAGE_LIST(mrpdu);
371 mrpdu_msg_eof = (unsigned char *)mrpdu_msg_ptr;
372 mrpdu_msg_eof += bytes;
373 mrpdu_msg_eof -= sizeof(eth_hdr_t);
374 mrpdu_msg_eof -= MRPD_OFFSETOF_MRPD_GET_MRPDU_MESSAGE_LIST;
377 * MVRP_VID_TYPE FirstValue is the 12 bit (2-byte) VLAN with
378 * corresponding attrib_length=2
380 * MVRP uses ThreePackedEvents for all vector encodings
382 * walk list until we run to the end of the PDU, or encounter a double end-mark
387 while (mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) {
388 mrpdu_msg = (mrpdu_message_t *) mrpdu_msg_ptr;
389 if ((mrpdu_msg->AttributeType == 0) &&
390 (mrpdu_msg->AttributeLength == 0)) {
394 continue; /* end-mark of message-list */
396 break; /* two endmarks - end of message list */
401 switch (mrpdu_msg->AttributeType) {
403 if (mrpdu_msg->AttributeLength != 2) {
404 /* we can seek for an endmark to recover .. but this version
405 * dumps the entire packet as malformed
409 /* AttributeListLength not used for MVRP, hence
410 * Data points to the beginning of the VectorAttributes
413 MRPD_GET_MRPDU_MESSAGE_VECTOR(mrpdu_msg, 0);
414 mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
416 while (!((mrpdu_msg_ptr[0] == 0)
417 && (mrpdu_msg_ptr[1] == 0))) {
419 MRPDU_VECT_NUMVALUES(ntohs
424 /* Malformed - cant tell how long the trailing vectors are */
427 if ((mrpdu_vectorptr->FirstValue_VectorEvents +
428 numvalues / 3) >= mrpdu_msg_eof)
429 /* Malformed - runs off the end of the pdu */
432 vid_firstval = (((uint16_t)
434 FirstValue_VectorEvents[0]) <<
437 FirstValue_VectorEvents[1];
439 /* if not an even multiple ... */
440 if (numvalues != ((numvalues / 3) * 3))
441 numvectorbytes = (numvalues / 3) + 1;
443 numvectorbytes = (numvalues / 3);
446 vectidx <= (numvectorbytes + 2);
450 FirstValue_VectorEvents[vectidx];
451 vectevt[0] = vect_3pack / 36;
453 (vect_3pack - vectevt[0] * 36) / 6;
455 vect_3pack - (36 * vectevt[0]) -
458 numvalues_processed =
459 (numvalues > 3 ? 3 : numvalues);
461 for (vectevt_idx = 0;
462 vectevt_idx < numvalues_processed;
465 if (0xFFF < vid_firstval) /*discard junk */
468 attrib = mvrp_alloc();
470 goto out; /* oops - internal error */
475 memcpy(attrib->registrar.
476 macaddr, eth->srcaddr,
479 switch (vectevt[vectevt_idx]) {
515 numvalues -= numvalues_processed;
519 (ntohs(mrpdu_vectorptr->VectorHeader)))
520 mvrp_event(MRP_EVENT_RLA, NULL);
522 /* 1 byte Type, 1 byte Len, 2 byte FirstValue, and (n) vector bytes */
523 mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
524 mrpdu_msg_ptr += 4 + numvectorbytes;
527 (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
531 /* unrecognized attribute type
532 * we can seek for an endmark to recover .. but this version
533 * dumps the entire packet as malformed
548 mvrp_emit_vidvectors(unsigned char *msgbuf, unsigned char *msgbuf_eof,
549 int *bytes_used, int lva)
551 mrpdu_vectorattrib_t *mrpdu_vectorptr;
555 unsigned int vectevt[3];
557 uint16_t vid_firstval;
558 struct mvrp_attribute *attrib, *vattrib;
559 mrpdu_message_t *mrpdu_msg;
561 unsigned char *mrpdu_msg_ptr = msgbuf;
562 unsigned char *mrpdu_msg_eof = msgbuf_eof;
564 /* need at least 6 bytes for a single vector */
565 if (mrpdu_msg_ptr > (mrpdu_msg_eof - 6))
568 mrpdu_msg = (mrpdu_message_t *) mrpdu_msg_ptr;
569 mrpdu_msg->AttributeType = MVRP_VID_TYPE;
570 mrpdu_msg->AttributeLength = 2;
572 attrib = MVRP_db->attrib_list;
574 mrpdu_vectorptr = MRPD_GET_MRPDU_MESSAGE_VECTOR(mrpdu_msg, 0);
576 while ((mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) && (NULL != attrib)) {
578 if (0 == attrib->applicant.tx) {
579 attrib = attrib->next;
582 if (MRP_ENCODE_OPTIONAL == attrib->applicant.encode) {
583 attrib->applicant.tx = 0;
584 attrib = attrib->next;
588 /* pointing to at least one attribute which needs to be transmitted */
589 attrib->applicant.tx = 0;
590 vid_firstval = attrib->attribute;
591 mrpdu_vectorptr->FirstValue_VectorEvents[0] =
592 (uint8_t) (attrib->attribute >> 8);
593 mrpdu_vectorptr->FirstValue_VectorEvents[1] =
594 (uint8_t) (attrib->attribute);
596 switch (attrib->applicant.sndmsg) {
599 * If 'In' in indicated by the applicant attribute, the
600 * look at the registrar state to determine whether to
601 * send an In (if registrar is also In) or an Mt if the
602 * registrar is either Mt or Lv.
604 if (MRP_IN_STATE == attrib->registrar.mrp_state)
605 vectevt[0] = MRPDU_IN;
607 vectevt[0] = MRPDU_MT;
610 vectevt[0] = MRPDU_NEW;
613 vectevt[0] = MRPDU_LV;
616 /* IF 'Join' in indicated by the applicant, look at
617 * the corresponding registrar state to determine whether
618 * to send a JoinIn (if the registar state is 'In') or
619 * a JoinMt if the registrar state is MT or LV.
621 if (MRP_IN_STATE == attrib->registrar.mrp_state)
622 vectevt[0] = MRPDU_JOININ;
624 vectevt[0] = MRPDU_JOINMT;
637 /* now attempt to vectorize contiguous other attributes
638 * which also need to be transmitted
642 vattrib = attrib->next;
644 while (NULL != vattrib) {
645 if (0 == vattrib->applicant.tx)
650 if (vattrib->attribute != vid_firstval)
653 vattrib->applicant.tx = 0;
655 switch (vattrib->applicant.sndmsg) {
658 * If 'In' in indicated by the applicant attribute, the
659 * look at the registrar state to determine whether to
660 * send an In (if registrar is also In) or an Mt if the
661 * registrar is either Mt or Lv.
664 vattrib->registrar.mrp_state)
665 vectevt[vectevt_idx] = MRPDU_IN;
667 vectevt[vectevt_idx] = MRPDU_MT;
670 vectevt[vectevt_idx] = MRPDU_NEW;
673 vectevt[vectevt_idx] = MRPDU_LV;
676 /* IF 'Join' in indicated by the applicant, look at
677 * the corresponding registrar state to determine whether
678 * to send a JoinIn (if the registar state is 'In') or
679 * a JoinMt if the registrar state is MT or LV.
681 if (MRP_IN_STATE == attrib->registrar.mrp_state)
682 vectevt[vectevt_idx] = MRPDU_JOININ;
684 vectevt[vectevt_idx] = MRPDU_JOINMT;
695 if (vectevt_idx > 2) {
696 vect_3pack = MRPDU_3PACK_ENCODE(vectevt[0],
700 mrpdu_vectorptr->FirstValue_VectorEvents
701 [vectidx] = vect_3pack;
709 if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx])
710 > (mrpdu_msg_eof - 2))
713 vattrib = vattrib->next;
716 /* handle any trailers */
717 if (vectevt_idx > 0) {
718 vect_3pack = MRPDU_3PACK_ENCODE(vectevt[0],
719 vectevt[1], vectevt[2]);
721 mrpdu_vectorptr->FirstValue_VectorEvents[vectidx] =
726 if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx]) >
730 mrpdu_vectorptr->VectorHeader = MRPDU_VECT_NUMVALUES(numvalues);
733 mrpdu_vectorptr->VectorHeader |= MRPDU_VECT_LVA(0xFFFF);
735 mrpdu_vectorptr->VectorHeader =
736 htons(mrpdu_vectorptr->VectorHeader);
738 /* 2 byte header, followed by FirstValues/Vectors - remember vectidx starts at 0 */
740 &(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx]);
742 attrib = attrib->next;
744 mrpdu_vectorptr = (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
747 if (mrpdu_vectorptr == MRPD_GET_MRPDU_MESSAGE_VECTOR(mrpdu_msg, 0)) {
758 *bytes_used = (mrpdu_msg_ptr - msgbuf);
761 /* an internal error - caller should assume TXLAF */
768 unsigned char *msgbuf, *msgbuf_wrptr;
773 unsigned char *mrpdu_msg_ptr;
774 unsigned char *mrpdu_msg_eof;
778 msgbuf = (unsigned char *)malloc(MAX_FRAME_SIZE);
783 msgbuf_wrptr = msgbuf;
785 eth = (eth_hdr_t *) msgbuf_wrptr;
787 /* note that MVRP frames should always be untagged (no vlan) */
788 eth->typelen = htons(MVRP_ETYPE);
789 memcpy(eth->destaddr, MVRP_CUSTOMER_BRIDGE_ADDR, sizeof(eth->destaddr));
790 memcpy(eth->srcaddr, STATION_ADDR, sizeof(eth->srcaddr));
792 msgbuf_wrptr += sizeof(eth_hdr_t);
794 mrpdu = (mrpdu_t *) msgbuf_wrptr;
797 * ProtocolVersion handling - a receiver must process received frames with a lesser
798 * protcol version consistent with the older protocol processing requirements (e.g. a V2
799 * agent receives a V1 message, the V1 message shoudl be parsed with V1 rules).
801 * However - if an agent receives a NEWER protocol, the agent shoudl still attempt
802 * to parse the frame. If the agent finds an AttributeType not recognized
803 * the agent discards the current message including any associated trailing vectors
804 * up to the end-mark, and resumes with the next message or until the end of the PDU
807 * If a VectorAttribute is found with an unknown Event for the Type, the specific
808 * VectorAttrute is discarded and processing continues with the next VectorAttribute.
811 mrpdu->ProtocolVersion = MVRP_PROT_VER;
812 mrpdu_msg_ptr = MRPD_GET_MRPDU_MESSAGE_LIST(mrpdu);
813 mrpdu_msg_eof = (unsigned char *)msgbuf + MAX_FRAME_SIZE;
816 * Iterate over all attributes, transmitting those marked
817 * with 'tx', attempting to coalesce multiple contiguous tx attributes
818 * with appropriate vector encodings.
820 * MVRP_VID_TYPE FirstValue is the 2-byte VLAN with
821 * corresponding attrib_length=2
823 * MVRP uses ThreePackedEvents for all vector encodings
825 * the expanded version of the MRPDU looks like
829 * <Variable number of>
830 * LeaveAllEvent | NumberOfValues
831 * <Variable FirstValue>
835 * in effect, each AttributeType present gets its own 'message' with
836 * variable number of vectors. So with MVRP, you will have at most
840 if (MVRP_db->mrp_db.lva.tx) {
842 MVRP_db->mrp_db.lva.tx = 0;
845 rc = mvrp_emit_vidvectors(mrpdu_msg_ptr, mrpdu_msg_eof, &bytes, lva);
849 mrpdu_msg_ptr += bytes;
851 if (mrpdu_msg_ptr == MRPD_GET_MRPDU_MESSAGE_LIST(mrpdu)) {
852 goto out; /* nothing to send */
856 if (mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) {
864 msgbuf_len = mrpdu_msg_ptr - msgbuf;
866 bytes = mrpd_send(mvrp_socket, msgbuf, msgbuf_len, 0);
874 /* caller should assume TXLAF */
878 int mvrp_send_notifications(struct mvrp_attribute *attrib, int notify)
889 msgbuf = (char *)malloc(MAX_MRPD_CMDSZ);
893 stage = variant = regsrc = NULL;
895 stage = (char *)malloc(128);
896 variant = (char *)malloc(128);
897 regsrc = (char *)malloc(128);
899 if ((NULL == stage) || (NULL == variant) || (NULL == regsrc))
902 memset(msgbuf, 0, MAX_MRPD_CMDSZ);
904 sprintf(variant, "%04x", attrib->attribute);
906 sprintf(regsrc, "R%02x%02x%02x%02x%02x%02x",
907 attrib->registrar.macaddr[0],
908 attrib->registrar.macaddr[1],
909 attrib->registrar.macaddr[2],
910 attrib->registrar.macaddr[3],
911 attrib->registrar.macaddr[4], attrib->registrar.macaddr[5]);
912 switch (attrib->registrar.mrp_state) {
914 sprintf(stage, "VIN %s %s\n", variant, regsrc);
917 sprintf(stage, "VLV %s %s\n", variant, regsrc);
920 sprintf(stage, "VMT %s %s\n", variant, regsrc);
928 snprintf(msgbuf, MAX_MRPD_CMDSZ - 1, "VNE %s", stage);
930 case MRP_NOTIFY_JOIN:
931 snprintf(msgbuf, MAX_MRPD_CMDSZ - 1, "VJO %s", stage);
934 snprintf(msgbuf, MAX_MRPD_CMDSZ - 1, "VLE %s", stage);
941 client = MVRP_db->mrp_db.clients;
942 while (NULL != client) {
943 mrpd_send_ctl_msg(&(client->client), msgbuf, MAX_MRPD_CMDSZ);
944 client = client->next;
958 int mvrp_dumptable(struct sockaddr_in *client)
965 struct mvrp_attribute *attrib;
967 msgbuf = (char *)malloc(MAX_MRPD_CMDSZ);
971 stage = variant = regsrc = NULL;
973 stage = (char *)malloc(128);
974 variant = (char *)malloc(128);
975 regsrc = (char *)malloc(128);
977 if ((NULL == stage) || (NULL == variant) || (NULL == regsrc))
980 memset(msgbuf, 0, MAX_MRPD_CMDSZ);
982 msgbuf_wrptr = msgbuf;
984 attrib = MVRP_db->attrib_list;
986 while (NULL != attrib) {
987 sprintf(variant, "%04x", attrib->attribute);
988 sprintf(regsrc, "R%02x%02x%02x%02x%02x%02x",
989 attrib->registrar.macaddr[0],
990 attrib->registrar.macaddr[1],
991 attrib->registrar.macaddr[2],
992 attrib->registrar.macaddr[3],
993 attrib->registrar.macaddr[4],
994 attrib->registrar.macaddr[5]);
995 switch (attrib->registrar.mrp_state) {
997 sprintf(stage, "VIN %s %s\n", variant, regsrc);
1000 sprintf(stage, "VLV %s %s\n", variant, regsrc);
1003 sprintf(stage, "VMT %s %s\n", variant, regsrc);
1008 sprintf(msgbuf_wrptr, "%s", stage);
1009 msgbuf_wrptr += strnlen(stage, 128);
1010 attrib = attrib->next;
1013 mrpd_send_ctl_msg(client, msgbuf, MAX_MRPD_CMDSZ);
1027 int mvrp_recv_cmd(char *buf, int buflen, struct sockaddr_in *client)
1031 struct mvrp_attribute *attrib;
1032 unsigned int vid_firstval;
1033 uint8_t vid_parsestr[8];
1035 if (NULL == MVRP_db) {
1036 snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
1037 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1041 rc = mrp_client_add(&(MVRP_db->mrp_db.clients), client);
1050 * V?? - query MVRP Registrar VID database
1052 * V++ NEW a VID (XXX: note network disturbance)
1057 mvrp_dumptable(client);
1061 snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1062 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1065 /* buf[] should look similar to 'V--0001' where VID is in hex */
1067 snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1068 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1072 memset(vid_parsestr, 0, sizeof(vid_parsestr));
1074 rc = sscanf((char *)&buf[3], "%04x", &vid_firstval);
1076 snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1077 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1081 attrib = mvrp_alloc();
1082 if (NULL == attrib) {
1083 snprintf(respbuf, sizeof(respbuf) - 1, "ERI %s", buf);
1084 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1085 goto out; /* oops - internal error */
1087 attrib->attribute = vid_firstval;
1088 memset(attrib->registrar.macaddr, 0, 6);
1090 mvrp_event(MRP_EVENT_LV, attrib);
1093 /* buf[] should look similar to 'V+?0001' where VID is in hex */
1094 if (('?' != buf[2]) && ('+' != buf[2])) {
1095 snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
1096 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1100 snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1101 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1104 rc = sscanf((char *)&buf[3], "%04x", &vid_firstval);
1107 snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1108 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1112 attrib = mvrp_alloc();
1113 if (NULL == attrib) {
1114 snprintf(respbuf, sizeof(respbuf) - 1, "ERI %s", buf);
1115 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1116 goto out; /* oops - internal error */
1118 attrib->attribute = vid_firstval;
1119 memset(attrib->registrar.macaddr, 0, 6);
1121 if ('?' == buf[2]) {
1122 mvrp_event(MRP_EVENT_JOIN, attrib);
1124 mvrp_event(MRP_EVENT_NEW, attrib);
1128 snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
1129 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1138 int mvrp_init(int mvrp_enable)
1142 /* XXX doesn't handle re-start */
1144 mvrp_socket = INVALID_SOCKET;
1147 if (0 == mvrp_enable) {
1151 rc = mrpd_init_protocol_socket(MVRP_ETYPE, &mvrp_socket,
1152 MVRP_CUSTOMER_BRIDGE_ADDR);
1156 MVRP_db = malloc(sizeof(struct mvrp_database));
1158 if (NULL == MVRP_db)
1161 memset(MVRP_db, 0, sizeof(struct mvrp_database));
1163 /* if registration is FIXED or FORBIDDEN
1164 * updates from MRP are discarded, and
1165 * only IN and JOININ messages are sent
1167 MVRP_db->mrp_db.registration = MRP_REGISTRAR_CTL_NORMAL; /* default */
1169 /* if participant role is 'SILENT' (or non-participant)
1170 * applicant doesn't send any messages -
1172 * Note - theoretically configured per-attribute
1174 MVRP_db->mrp_db.participant = MRP_APPLICANT_CTL_NORMAL; /* default */
1176 rc = mrpd_init_timers(&(MVRP_db->mrp_db));
1181 mrp_lvatimer_fsm(&(MVRP_db->mrp_db), MRP_EVENT_BEGIN);
1185 /* free MVRP_db and related structures */
1189 mrpd_close_socket(mvrp_socket);
1190 mvrp_socket = INVALID_SOCKET;
1195 int mvrp_reclaim(void)
1197 struct mvrp_attribute *vattrib, *free_vattrib;
1198 if (NULL == MVRP_db)
1201 vattrib = MVRP_db->attrib_list;
1202 while (NULL != vattrib) {
1203 if ((vattrib->registrar.mrp_state == MRP_MT_STATE) &&
1204 ((vattrib->applicant.mrp_state == MRP_VO_STATE) ||
1205 (vattrib->applicant.mrp_state == MRP_AO_STATE) ||
1206 (vattrib->applicant.mrp_state == MRP_QO_STATE))) {
1207 if (NULL != vattrib->prev)
1208 vattrib->prev->next = vattrib->next;
1210 MVRP_db->attrib_list = vattrib->next;
1211 if (NULL != vattrib->next)
1212 vattrib->next->prev = vattrib->prev;
1213 free_vattrib = vattrib;
1214 vattrib = vattrib->next;
1215 mvrp_send_notifications(free_vattrib, MRP_NOTIFY_LV);
1218 vattrib = vattrib->next;
1223 void mvrp_bye(struct sockaddr_in *client)
1225 if (NULL != MVRP_db)
1226 mrp_client_delete(&(MVRP_db->mrp_db.clients), client);