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)
40 #include <netinet/in.h>
46 int mvrp_send_notifications(struct mvrp_attribute *attrib, int notify);
49 unsigned char MVRP_CUSTOMER_BRIDGE_ADDR[] = \
50 { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x21 }; /* 81-00 */
51 unsigned char MVRP_PROVIDER_BRIDGE_ADDR[] = \
52 { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x0D }; /* 88-A8 */
53 extern unsigned char STATION_ADDR[];
55 /* global variables */
57 struct mvrp_database *MVRP_db;
61 struct mvrp_attribute *mvrp_lookup(struct mvrp_attribute *rattrib)
63 struct mvrp_attribute *attrib;
65 attrib = MVRP_db->attrib_list;
66 while (NULL != attrib) {
67 if (attrib->attribute == rattrib->attribute)
69 attrib = attrib->next;
74 int mvrp_add(struct mvrp_attribute *rattrib)
76 struct mvrp_attribute *attrib;
77 struct mvrp_attribute *attrib_tail;
79 /* XXX do a lookup first to guarantee uniqueness? */
81 attrib_tail = attrib = MVRP_db->attrib_list;
83 while (NULL != attrib) {
84 if (attrib->attribute < rattrib->attribute) {
85 /* possible tail insertion ... */
86 if (NULL != attrib->next) {
87 attrib = attrib->next;
90 rattrib->next = attrib->next;
91 rattrib->prev = attrib;
92 attrib->next = rattrib;
96 /* head insertion ... */
97 rattrib->next = attrib;
98 rattrib->prev = attrib->prev;
99 attrib->prev = rattrib;
100 if (NULL != rattrib->prev)
101 rattrib->prev->next = rattrib;
103 MVRP_db->attrib_list = rattrib;
107 attrib_tail = attrib;
108 attrib = attrib->next;
111 /* if we are here we didn't need to stitch in a a sorted entry
112 * so append it onto the tail (if it exists)
115 if (NULL == attrib_tail) {
116 rattrib->next = NULL;
117 rattrib->prev = NULL;
118 MVRP_db->attrib_list = rattrib;
120 rattrib->next = NULL;
121 rattrib->prev = attrib_tail;
122 attrib_tail->next = rattrib;
128 int mvrp_merge(struct mvrp_attribute *rattrib)
130 struct mvrp_attribute *attrib;
132 attrib = mvrp_lookup(rattrib);
135 return -1; /* shouldn't happen */
137 /* primarily we update the last mac address state for diagnostics */
138 memcpy(attrib->registrar.macaddr, rattrib->registrar.macaddr, 6);
142 int mvrp_event(int event, struct mvrp_attribute *rattrib)
144 struct mvrp_attribute *attrib;
148 case MRP_EVENT_LVATIMER:
149 mrp_jointimer_stop(&(MVRP_db->mrp_db));
151 attrib = MVRP_db->attrib_list;
153 while (NULL != attrib) {
154 mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_TXLA);
155 mrp_registrar_fsm(&(attrib->registrar),
156 &(MVRP_db->mrp_db), MRP_EVENT_TXLA);
157 attrib = attrib->next;
160 mrp_lvatimer_fsm(&(MVRP_db->mrp_db), MRP_EVENT_LVATIMER);
165 mrp_jointimer_stop(&(MVRP_db->mrp_db));
167 attrib = MVRP_db->attrib_list;
169 while (NULL != attrib) {
170 mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_RLA);
171 mrp_registrar_fsm(&(attrib->registrar),
172 &(MVRP_db->mrp_db), MRP_EVENT_RLA);
173 attrib = attrib->next;
176 mrp_lvatimer_fsm(&(MVRP_db->mrp_db), MRP_EVENT_RLA);
180 mrp_jointimer_stop(&(MVRP_db->mrp_db));
181 attrib = MVRP_db->attrib_list;
183 while (NULL != attrib) {
184 mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_TX);
185 attrib = attrib->next;
188 mrp_lvatimer_fsm(&(MVRP_db->mrp_db), MRP_EVENT_TX);
192 case MRP_EVENT_LVTIMER:
193 mrp_lvtimer_stop(&(MVRP_db->mrp_db));
194 attrib = MVRP_db->attrib_list;
196 while (NULL != attrib) {
197 mrp_registrar_fsm(&(attrib->registrar),
201 attrib = attrib->next;
204 case MRP_EVENT_PERIODIC:
205 attrib = MVRP_db->attrib_list;
207 while (NULL != attrib) {
208 mrp_applicant_fsm(&(attrib->applicant),
210 attrib = attrib->next;
216 case MRP_EVENT_RJOININ:
217 case MRP_EVENT_RJOINMT:
222 mrp_jointimer_start(&(MVRP_db->mrp_db));
224 return -1; /* XXX internal fault */
227 attrib = mvrp_lookup(rattrib);
229 if (NULL == attrib) {
237 mrp_applicant_fsm(&(attrib->applicant), event);
238 /* remap local requests into registrar events */
241 mrp_registrar_fsm(&(attrib->registrar),
242 &(MVRP_db->mrp_db), MRP_EVENT_RNEW);
245 if (MRP_IN_STATE == attrib->registrar.mrp_state)
246 mrp_registrar_fsm(&(attrib->registrar),
250 mrp_registrar_fsm(&(attrib->registrar),
255 mrp_registrar_fsm(&(attrib->registrar),
256 &(MVRP_db->mrp_db), MRP_EVENT_RLV);
259 rc = mrp_registrar_fsm(&(attrib->registrar),
260 &(MVRP_db->mrp_db), event);
263 ("MVRP registrar error on attrib->attribute = %d\n",
274 * XXX should honor the MVRP_db->mrp_db.registration and
275 * MVRP_db->mrp_db.participant controls
278 /* generate local notifications */
279 attrib = MVRP_db->attrib_list;
281 while (NULL != attrib) {
282 if (MRP_NOTIFY_NONE != attrib->registrar.notify) {
283 mvrp_send_notifications(attrib,
284 attrib->registrar.notify);
285 attrib->registrar.notify = MRP_NOTIFY_NONE;
287 attrib = attrib->next;
293 struct mvrp_attribute *mvrp_alloc()
295 struct mvrp_attribute *attrib;
297 attrib = malloc(sizeof(struct mvrp_attribute));
301 memset(attrib, 0, sizeof(struct mvrp_attribute));
303 attrib->applicant.mrp_state = MRP_VO_STATE;
304 attrib->applicant.tx = 0;
305 attrib->applicant.sndmsg = MRP_SND_NULL;
306 attrib->applicant.encode = MRP_ENCODE_OPTIONAL;
308 attrib->registrar.mrp_state = MRP_MT_STATE;
309 attrib->registrar.notify = MRP_NOTIFY_NONE;
314 int mvrp_recv_msg(void)
320 mrpdu_message_t *mrpdu_msg;
321 unsigned char *mrpdu_msg_ptr;
322 unsigned char *mrpdu_msg_eof;
323 mrpdu_vectorattrib_t *mrpdu_vectorptr;
325 u_int16_t numvalues_processed;
331 u_int16_t vid_firstval;
332 struct mvrp_attribute *attrib;
335 bytes = mrpd_recvmsgbuf(mvrp_socket, &msgbuf);
339 if ((unsigned int)bytes < (sizeof(eth_hdr_t) + sizeof(mrpdu_t) +
340 sizeof(mrpdu_message_t)))
343 eth = (eth_hdr_t *) msgbuf;
345 /* note that MVRP frames should always arrive untagged (no vlan) */
346 if (MVRP_ETYPE != ntohs(eth->typelen))
349 /* XXX check dest mac address too? */
351 mrpdu = (mrpdu_t *) (msgbuf + sizeof(struct eth_hdr));
354 * ProtocolVersion handling - a receiver must process received frames with a lesser
355 * protcol version consistent with the older protocol processing requirements (e.g. a V2
356 * agent receives a V1 message, the V1 message shoudl be parsed with V1 rules).
358 * However - if an agent receives a NEWER protocol, the agent shoudl still attempt
359 * to parse the frame. If the agent finds an AttributeType not recognized
360 * the agent discards the current message including any associated trailing vectors
361 * up to the end-mark, and resumes with the next message or until the end of the PDU
364 * If a VectorAttribute is found with an unknown Event for the Type, the specific
365 * VectorAttrute is discarded and processing continues with the next VectorAttribute.
368 if (MVRP_PROT_VER != mrpdu->ProtocolVersion) /* XXX should accept ... */
371 mrpdu_msg_ptr = (unsigned char *)mrpdu->MessageList;
373 mrpdu_msg_eof = (unsigned char *)mrpdu_msg_ptr;
374 mrpdu_msg_eof += bytes;
375 mrpdu_msg_eof -= sizeof(eth_hdr_t);
376 mrpdu_msg_eof -= offsetof(mrpdu_t, MessageList);
379 * MVRP_VID_TYPE FirstValue is the 12 bit (2-byte) VLAN with
380 * corresponding attrib_length=2
382 * MVRP uses ThreePackedEvents for all vector encodings
384 * walk list until we run to the end of the PDU, or encounter a double end-mark
389 while (mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) {
390 mrpdu_msg = (mrpdu_message_t *) mrpdu_msg_ptr;
391 if ((mrpdu_msg->AttributeType == 0) &&
392 (mrpdu_msg->AttributeLength == 0)) {
396 continue; /* end-mark of message-list */
398 break; /* two endmarks - end of message list */
403 switch (mrpdu_msg->AttributeType) {
405 if (mrpdu_msg->AttributeLength != 2) {
406 /* we can seek for an endmark to recover .. but this version
407 * dumps the entire packet as malformed
411 /* AttributeListLength not used for MVRP, hence
412 * Data points to the beginning of the VectorAttributes
415 (mrpdu_vectorattrib_t *) mrpdu_msg->Data;
416 mrpdu_msg_ptr = (u_int8_t *) mrpdu_vectorptr;
419 ((mrpdu_msg_ptr[0] == 0)
420 && (mrpdu_msg_ptr[1] == 0))) {
422 MRPDU_VECT_NUMVALUES(ntohs
427 /* Malformed - cant tell how long the trailing vectors are */
430 if ((mrpdu_vectorptr->FirstValue_VectorEvents +
431 numvalues / 3) >= mrpdu_msg_eof)
432 /* Malformed - runs off the end of the pdu */
436 (((u_int16_t) mrpdu_vectorptr->
437 FirstValue_VectorEvents[0]) << 8)
439 FirstValue_VectorEvents[1];
441 /* if not an even multiple ... */
442 if (numvalues != ((numvalues / 3) * 3))
443 numvectorbytes = (numvalues / 3) + 1;
445 numvectorbytes = (numvalues / 3);
448 vectidx <= (numvectorbytes + 2);
452 FirstValue_VectorEvents[vectidx];
453 vectevt[0] = vect_3pack / 36;
455 (vect_3pack - vectevt[0] * 36) / 6;
457 vect_3pack - (36 * vectevt[0]) -
460 numvalues_processed =
461 (numvalues > 3 ? 3 : numvalues);
463 for (vectevt_idx = 0;
464 vectevt_idx < numvalues_processed;
467 if (0xFFF < vid_firstval) /*discard junk */
470 attrib = mvrp_alloc();
472 goto out; /* oops - internal error */
477 memcpy(attrib->registrar.
478 macaddr, eth->srcaddr,
481 switch (vectevt[vectevt_idx]) {
517 numvalues -= numvalues_processed;
521 (ntohs(mrpdu_vectorptr->VectorHeader)))
522 mvrp_event(MRP_EVENT_RLA, NULL);
524 /* 1 byte Type, 1 byte Len, 2 byte FirstValue, and (n) vector bytes */
525 mrpdu_msg_ptr = (u_int8_t *) mrpdu_vectorptr;
526 mrpdu_msg_ptr += 4 + numvectorbytes;
529 (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
533 /* unrecognized attribute type
534 * we can seek for an endmark to recover .. but this version
535 * dumps the entire packet as malformed
550 mvrp_emit_vidvectors(unsigned char *msgbuf, unsigned char *msgbuf_eof,
551 int *bytes_used, int lva)
553 mrpdu_vectorattrib_t *mrpdu_vectorptr;
557 unsigned int vectevt[3];
559 u_int16_t vid_firstval;
560 struct mvrp_attribute *attrib, *vattrib;
561 mrpdu_message_t *mrpdu_msg;
563 unsigned char *mrpdu_msg_ptr = msgbuf;
564 unsigned char *mrpdu_msg_eof = msgbuf_eof;
566 /* need at least 6 bytes for a single vector */
567 if (mrpdu_msg_ptr > (mrpdu_msg_eof - 6))
570 mrpdu_msg = (mrpdu_message_t *) mrpdu_msg_ptr;
571 mrpdu_msg->AttributeType = MVRP_VID_TYPE;
572 mrpdu_msg->AttributeLength = 2;
574 attrib = MVRP_db->attrib_list;
576 mrpdu_vectorptr = (mrpdu_vectorattrib_t *) mrpdu_msg->Data;
578 while ((mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) && (NULL != attrib)) {
580 if (0 == attrib->applicant.tx) {
581 attrib = attrib->next;
584 if (MRP_ENCODE_OPTIONAL == attrib->applicant.encode) {
585 attrib->applicant.tx = 0;
586 attrib = attrib->next;
590 /* pointing to at least one attribute which needs to be transmitted */
591 attrib->applicant.tx = 0;
592 vid_firstval = attrib->attribute;
593 mrpdu_vectorptr->FirstValue_VectorEvents[0] =
594 (u_int8_t) (attrib->attribute >> 8);
595 mrpdu_vectorptr->FirstValue_VectorEvents[1] =
596 (u_int8_t) (attrib->attribute);
598 switch (attrib->applicant.sndmsg) {
601 * If 'In' in indicated by the applicant attribute, the
602 * look at the registrar state to determine whether to
603 * send an In (if registrar is also In) or an Mt if the
604 * registrar is either Mt or Lv.
606 if (MRP_IN_STATE == attrib->registrar.mrp_state)
607 vectevt[0] = MRPDU_IN;
609 vectevt[0] = MRPDU_MT;
612 vectevt[0] = MRPDU_NEW;
615 vectevt[0] = MRPDU_LV;
618 /* IF 'Join' in indicated by the applicant, look at
619 * the corresponding registrar state to determine whether
620 * to send a JoinIn (if the registar state is 'In') or
621 * a JoinMt if the registrar state is MT or LV.
623 if (MRP_IN_STATE == attrib->registrar.mrp_state)
624 vectevt[0] = MRPDU_JOININ;
626 vectevt[0] = MRPDU_JOINMT;
639 /* now attempt to vectorize contiguous other attributes
640 * which also need to be transmitted
644 vattrib = attrib->next;
646 while (NULL != vattrib) {
647 if (0 == vattrib->applicant.tx)
652 if (vattrib->attribute != vid_firstval)
655 vattrib->applicant.tx = 0;
657 switch (vattrib->applicant.sndmsg) {
660 * If 'In' in indicated by the applicant attribute, the
661 * look at the registrar state to determine whether to
662 * send an In (if registrar is also In) or an Mt if the
663 * registrar is either Mt or Lv.
666 vattrib->registrar.mrp_state)
667 vectevt[vectevt_idx] = MRPDU_IN;
669 vectevt[vectevt_idx] = MRPDU_MT;
672 vectevt[vectevt_idx] = MRPDU_NEW;
675 vectevt[vectevt_idx] = MRPDU_LV;
678 /* IF 'Join' in indicated by the applicant, look at
679 * the corresponding registrar state to determine whether
680 * to send a JoinIn (if the registar state is 'In') or
681 * a JoinMt if the registrar state is MT or LV.
683 if (MRP_IN_STATE == attrib->registrar.mrp_state)
684 vectevt[vectevt_idx] = MRPDU_JOININ;
686 vectevt[vectevt_idx] = MRPDU_JOINMT;
697 if (vectevt_idx > 2) {
698 vect_3pack = MRPDU_3PACK_ENCODE(vectevt[0],
703 FirstValue_VectorEvents[vectidx] =
712 if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx])
713 > (mrpdu_msg_eof - 2))
716 vattrib = vattrib->next;
719 /* handle any trailers */
720 if (vectevt_idx > 0) {
721 vect_3pack = MRPDU_3PACK_ENCODE(vectevt[0],
722 vectevt[1], vectevt[2]);
724 mrpdu_vectorptr->FirstValue_VectorEvents[vectidx] =
729 if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx]) >
733 mrpdu_vectorptr->VectorHeader = MRPDU_VECT_NUMVALUES(numvalues);
736 mrpdu_vectorptr->VectorHeader |= MRPDU_VECT_LVA(0xFFFF);
738 mrpdu_vectorptr->VectorHeader =
739 htons(mrpdu_vectorptr->VectorHeader);
741 /* 2 byte header, followed by FirstValues/Vectors - remember vectidx starts at 0 */
743 &(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx]);
745 attrib = attrib->next;
747 mrpdu_vectorptr = (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
750 if (mrpdu_vectorptr == (mrpdu_vectorattrib_t *) mrpdu_msg->Data) {
761 *bytes_used = (mrpdu_msg_ptr - msgbuf);
764 /* an internal error - caller should assume TXLAF */
771 unsigned char *msgbuf, *msgbuf_wrptr;
776 unsigned char *mrpdu_msg_ptr;
777 unsigned char *mrpdu_msg_eof;
781 msgbuf = (unsigned char *)malloc(MAX_FRAME_SIZE);
786 msgbuf_wrptr = msgbuf;
788 eth = (eth_hdr_t *) msgbuf_wrptr;
790 /* note that MVRP frames should always be untagged (no vlan) */
791 eth->typelen = htons(MVRP_ETYPE);
792 memcpy(eth->destaddr, MVRP_CUSTOMER_BRIDGE_ADDR, sizeof(eth->destaddr));
793 memcpy(eth->srcaddr, STATION_ADDR, sizeof(eth->srcaddr));
795 msgbuf_wrptr += sizeof(eth_hdr_t);
797 mrpdu = (mrpdu_t *) msgbuf_wrptr;
800 * ProtocolVersion handling - a receiver must process received frames with a lesser
801 * protcol version consistent with the older protocol processing requirements (e.g. a V2
802 * agent receives a V1 message, the V1 message shoudl be parsed with V1 rules).
804 * However - if an agent receives a NEWER protocol, the agent shoudl still attempt
805 * to parse the frame. If the agent finds an AttributeType not recognized
806 * the agent discards the current message including any associated trailing vectors
807 * up to the end-mark, and resumes with the next message or until the end of the PDU
810 * If a VectorAttribute is found with an unknown Event for the Type, the specific
811 * VectorAttrute is discarded and processing continues with the next VectorAttribute.
814 mrpdu->ProtocolVersion = MVRP_PROT_VER;
815 mrpdu_msg_ptr = (unsigned char *)mrpdu->MessageList;
816 mrpdu_msg_eof = (unsigned char *)msgbuf + MAX_FRAME_SIZE;
819 * Iterate over all attributes, transmitting those marked
820 * with 'tx', attempting to coalesce multiple contiguous tx attributes
821 * with appropriate vector encodings.
823 * MVRP_VID_TYPE FirstValue is the 2-byte VLAN with
824 * corresponding attrib_length=2
826 * MVRP uses ThreePackedEvents for all vector encodings
828 * the expanded version of the MRPDU looks like
832 * <Variable number of>
833 * LeaveAllEvent | NumberOfValues
834 * <Variable FirstValue>
838 * in effect, each AttributeType present gets its own 'message' with
839 * variable number of vectors. So with MVRP, you will have at most
843 if (MVRP_db->mrp_db.lva.tx) {
845 MVRP_db->mrp_db.lva.tx = 0;
848 rc = mvrp_emit_vidvectors(mrpdu_msg_ptr, mrpdu_msg_eof, &bytes, lva);
852 mrpdu_msg_ptr += bytes;
854 if (mrpdu_msg_ptr == (unsigned char *)mrpdu->MessageList) {
855 goto out; /* nothing to send */
859 if (mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) {
867 msgbuf_len = mrpdu_msg_ptr - msgbuf;
869 bytes = send(mvrp_socket, msgbuf, msgbuf_len, 0);
877 /* caller should assume TXLAF */
881 int mvrp_send_notifications(struct mvrp_attribute *attrib, int notify)
892 msgbuf = (char *)malloc(MAX_MRPD_CMDSZ);
896 stage = variant = regsrc = NULL;
898 stage = (char *)malloc(128);
899 variant = (char *)malloc(128);
900 regsrc = (char *)malloc(128);
902 if ((NULL == stage) || (NULL == variant) || (NULL == regsrc))
905 memset(msgbuf, 0, MAX_MRPD_CMDSZ);
907 sprintf(variant, "%04x", attrib->attribute);
909 sprintf(regsrc, "R%02x%02x%02x%02x%02x%02x",
910 attrib->registrar.macaddr[0],
911 attrib->registrar.macaddr[1],
912 attrib->registrar.macaddr[2],
913 attrib->registrar.macaddr[3],
914 attrib->registrar.macaddr[4], attrib->registrar.macaddr[5]);
915 switch (attrib->registrar.mrp_state) {
917 sprintf(stage, "VIN %s %s\n", variant, regsrc);
920 sprintf(stage, "VLV %s %s\n", variant, regsrc);
923 sprintf(stage, "VMT %s %s\n", variant, regsrc);
931 snprintf(msgbuf, MAX_MRPD_CMDSZ - 1, "VNE %s", stage);
933 case MRP_NOTIFY_JOIN:
934 snprintf(msgbuf, MAX_MRPD_CMDSZ - 1, "VJO %s", stage);
937 snprintf(msgbuf, MAX_MRPD_CMDSZ - 1, "VLE %s", stage);
944 client = MVRP_db->mrp_db.clients;
945 while (NULL != client) {
946 mrpd_send_ctl_msg(&(client->client), msgbuf, MAX_MRPD_CMDSZ);
947 client = client->next;
961 int mvrp_dumptable(struct sockaddr_in *client)
968 struct mvrp_attribute *attrib;
970 msgbuf = (char *)malloc(MAX_MRPD_CMDSZ);
974 stage = variant = regsrc = NULL;
976 stage = (char *)malloc(128);
977 variant = (char *)malloc(128);
978 regsrc = (char *)malloc(128);
980 if ((NULL == stage) || (NULL == variant) || (NULL == regsrc))
983 memset(msgbuf, 0, MAX_MRPD_CMDSZ);
985 msgbuf_wrptr = msgbuf;
987 attrib = MVRP_db->attrib_list;
989 while (NULL != attrib) {
990 sprintf(variant, "%04x", attrib->attribute);
991 sprintf(regsrc, "R%02x%02x%02x%02x%02x%02x",
992 attrib->registrar.macaddr[0],
993 attrib->registrar.macaddr[1],
994 attrib->registrar.macaddr[2],
995 attrib->registrar.macaddr[3],
996 attrib->registrar.macaddr[4],
997 attrib->registrar.macaddr[5]);
998 switch (attrib->registrar.mrp_state) {
1000 sprintf(stage, "VIN %s %s\n", variant, regsrc);
1003 sprintf(stage, "VLV %s %s\n", variant, regsrc);
1006 sprintf(stage, "VMT %s %s\n", variant, regsrc);
1011 sprintf(msgbuf_wrptr, "%s", stage);
1012 msgbuf_wrptr += strnlen(stage, 128);
1013 attrib = attrib->next;
1016 mrpd_send_ctl_msg(client, msgbuf, MAX_MRPD_CMDSZ);
1030 int mvrp_recv_cmd(char *buf, int buflen, struct sockaddr_in *client)
1034 struct mvrp_attribute *attrib;
1035 unsigned int vid_firstval;
1036 u_int8_t vid_parsestr[8];
1038 if (NULL == MVRP_db) {
1039 snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
1040 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1044 rc = mrp_client_add(&(MVRP_db->mrp_db.clients), client);
1053 * V?? - query MVRP Registrar VID database
1055 * V++ NEW a VID (XXX: note network disturbance)
1060 mvrp_dumptable(client);
1064 snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1065 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1068 /* buf[] should look similar to 'V--0001' where VID is in hex */
1070 snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1071 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1075 memset(vid_parsestr, 0, sizeof(vid_parsestr));
1077 rc = sscanf((char *)&buf[3], "%04x", &vid_firstval);
1079 snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1080 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1084 attrib = mvrp_alloc();
1085 if (NULL == attrib) {
1086 snprintf(respbuf, sizeof(respbuf) - 1, "ERI %s", buf);
1087 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1088 goto out; /* oops - internal error */
1090 attrib->attribute = vid_firstval;
1091 memset(attrib->registrar.macaddr, 0, 6);
1093 mvrp_event(MRP_EVENT_LV, attrib);
1096 /* buf[] should look similar to 'V+?0001' where VID is in hex */
1097 if (('?' != buf[2]) && ('+' != buf[2])) {
1098 snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
1099 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1103 snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1104 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1107 rc = sscanf((char *)&buf[3], "%04x", &vid_firstval);
1110 snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1111 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1115 attrib = mvrp_alloc();
1116 if (NULL == attrib) {
1117 snprintf(respbuf, sizeof(respbuf) - 1, "ERI %s", buf);
1118 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1119 goto out; /* oops - internal error */
1121 attrib->attribute = vid_firstval;
1122 memset(attrib->registrar.macaddr, 0, 6);
1124 if ('?' == buf[2]) {
1125 mvrp_event(MRP_EVENT_JOIN, attrib);
1127 mvrp_event(MRP_EVENT_NEW, attrib);
1131 snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
1132 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1141 int mvrp_init(int mvrp_enable)
1145 /* XXX doesn't handle re-start */
1147 mvrp_socket = INVALID_SOCKET;
1150 if (0 == mvrp_enable) {
1154 rc = mrpd_init_protocol_socket(MVRP_ETYPE, &mvrp_socket,
1155 MVRP_CUSTOMER_BRIDGE_ADDR);
1159 MVRP_db = malloc(sizeof(struct mvrp_database));
1161 if (NULL == MVRP_db)
1164 memset(MVRP_db, 0, sizeof(struct mvrp_database));
1166 /* if registration is FIXED or FORBIDDEN
1167 * updates from MRP are discarded, and
1168 * only IN and JOININ messages are sent
1170 MVRP_db->mrp_db.registration = MRP_REGISTRAR_CTL_NORMAL; /* default */
1172 /* if participant role is 'SILENT' (or non-participant)
1173 * applicant doesn't send any messages -
1175 * Note - theoretically configured per-attribute
1177 MVRP_db->mrp_db.participant = MRP_APPLICANT_CTL_NORMAL; /* default */
1179 rc = mrp_init_timers(&(MVRP_db->mrp_db));
1184 mrp_lvatimer_fsm(&(MVRP_db->mrp_db), MRP_EVENT_BEGIN);
1188 /* free MVRP_db and related structures */
1198 int mvrp_reclaim(void)
1200 struct mvrp_attribute *vattrib, *free_vattrib;
1201 if (NULL == MVRP_db)
1204 vattrib = MVRP_db->attrib_list;
1205 while (NULL != vattrib) {
1206 if ((vattrib->registrar.mrp_state == MRP_MT_STATE) &&
1207 ((vattrib->applicant.mrp_state == MRP_VO_STATE) ||
1208 (vattrib->applicant.mrp_state == MRP_AO_STATE) ||
1209 (vattrib->applicant.mrp_state == MRP_QO_STATE)))
1211 if (NULL != vattrib->prev)
1212 vattrib->prev->next = vattrib->next;
1214 MVRP_db->attrib_list = vattrib->next;
1215 if (NULL != vattrib->next)
1216 vattrib->next->prev = vattrib->prev;
1217 free_vattrib = vattrib;
1218 vattrib = vattrib->next;
1219 mvrp_send_notifications(free_vattrib, MRP_NOTIFY_LV);
1222 vattrib = vattrib->next;
1227 void mvrp_bye(struct sockaddr_in *client)
1229 if (NULL != MVRP_db)
1230 mrp_client_delete(&(MVRP_db->mrp_db.clients), client);